Bash 带有“或”条件的sed替换似乎不起作用
当涉及插入/替换时,我的sed regex或似乎不起作用。给定以下数据文件,如果在第五个字段之后存在关键字,我想在关键字之前插入回车符。然后,想法是打印单独的行。我知道Python、Perl等会更好,但BourneShell是必需的 data.txt:Bash 带有“或”条件的sed替换似乎不起作用,bash,sed,sh,Bash,Sed,Sh,当涉及插入/替换时,我的sed regex或似乎不起作用。给定以下数据文件,如果在第五个字段之后存在关键字,我想在关键字之前插入回车符。然后,想法是打印单独的行。我知道Python、Perl等会更好,但BourneShell是必需的 data.txt: field1 field2 field3 field4 field5 first('echo hello') second('ls /tmp') field1 field2 field3 field4 field5 second('ls -la
field1 field2 field3 field4 field5 first('echo hello') second('ls /tmp')
field1 field2 field3 field4 field5 second('ls -la /home') forth('ls /tmp')
field1 field2 field3 field4 field5 first ('touch /tmp/hello')
field1 field2 field3 field4 field5 fifth('echo hello world') first('ls /etc') third ('mkdir -p /tmp/blah')
script.sh
#!/bin/sh
while read line; do
oldifs="$IFS"
scriptlets=$(echo $line | cut -d ' ' -f 6- | sed -e "s=\(first|second|third|forth|fifth\)=\'$'\n\1=g")
IFS=$'\n' # this works for Bourne shell 3.2.57
for scriptlet in $scriptlets; do
echo "-> $scriptlet"
done
IFS="$oldifs"
echo ""
done < ./data.txt
在-E下的sed中,分组括号不应反斜杠。反斜杠括号与文字括号匹配
此外,您对$scriptlets的赋值缺少用于命令替换的右括号。另外,是否确实要使用命令替换两次,一次在赋值中,一次在for循环中
最后,您可能指的是while read line,而不是for read line,这毫无意义。这是一条注释,但太长了。有关正确的解决方案,请参阅
这里有很多问题
对于读取行无效;你的意思可能是读台词的时候。
Scriptlet=$。。。缺少一个结束语。
$scriptlets可能不是您想要的-您可能是指${scriptlets}
回音$线有问题。您可能需要引用该变量
Bash与bourneshell不同,尽管它是兼容的。例如,Bourne shell不支持C样式的字符串$'…',如IFS=$'\n中所示。
\n是换行符,\r是回车符。这更像是吹毛求疵,但它可能会让阅读问题的人感到困惑。
尝试使用调试。显然,您不能将sed或和替换/插入组合在一起。因此,我需要将sed语句分解为单独的语句
scriptlets=$(echo $line | cut -d ' ' -f 6- | sed -e 's/ first/\'$'\nfirst/' -e 's/second/\'$'\nsecond/' -e 's/ third/\'$'\nthird/' -e 's/forth/\'$'\nforth/' -e 's/ fifth/\'$'\nfifth/')
默认情况下,sed使用基本的正则表达式语法,它不支持您所说的交替。要使用交替,请使用sed-E和扩展正则表达式语法。此外,在替换模式中插入换行符的语法也是混乱的。请尝试以下方法:
nl=$'\n'
... | sed -E $'s=(first|second|third|forth|fifth)=\\\n\\1=g' )
但事实上,我也建议用不同的方式编写周围的代码。它当前逐个读取文件中的行,通过cut和sed one传递它们,收集输出,然后使用for将其拆分为更多行。为什么不一次通过cut和sed传递整个文件,然后从中分割输出?另外,通常最好使用while-read循环在行上循环,因为它不会对shell通配符进行愚蠢的操作。这个怎么样:
#!/bin/sh
cut -d ' ' -f 6- data.txt | \
sed -E $'s=(first|second|third|forth|fifth)=\\\n\\1=g' | \
while read scriptlet; do
echo "-> $scriptlet"
done
echo
注意,这会导致循环在子shell中运行,因为它在管道中。如果这是一个问题,您需要bash而不是plain sh及其进程替换功能:
#!/bin/bash
while read scriptlet; do
echo "-> $scriptlet"
done < <(cut -d ' ' -f 6- data.txt | \
sed -E $'s=(first|second|third|forth|fifth)=\\\n\\1=g' )
echo
bash不是bourneshell,实际上没有人再使用它了。bash:bourneshell。我想很容易把它们混在一起。
#!/bin/bash
while read scriptlet; do
echo "-> $scriptlet"
done < <(cut -d ' ' -f 6- data.txt | \
sed -E $'s=(first|second|third|forth|fifth)=\\\n\\1=g' )
echo