我尝试使用变量(行位置)作为“剪切”文件的参数,但我在 sed 命令中遇到错误。
这是我的代码:
START=$(grep -n "pattern1" $FILE | cut -f1 | sed 's/:.*$//g')
END=$(grep -n "pattern2" $FILE | cut -f1 | sed 's/:.*$//g')
sed -n '${START},${END}p' $FILE > temp; # error here
# sed: -e expression #1, char 3: unknown command: `S'
但当我使用数字时它会起作用:
sed -n '28,63p' $FILE > temp;
看来是需要申请一些逃生,但我无法解决。有什么建议吗?非常感谢!
答案1
您的代码的主要问题是您期望 shell在单引号字符串中扩展您的START
和变量。 END
shell 永远不会这样做,这是单引号字符串和双引号字符串之间的主要区别之一。
相反,请在表达式中使用双引号字符串sed
。
然而,您似乎还期望您的两个grep
管道分别返回一个行号,在这种情况下,我看不到它们的原因,因为您可以sed
直接执行此表单。sed
如果命令采用多个地址,则命令采用行号、正则表达式或这些形式的组合形式的地址。
sed -n '/pattern1/,/pattern2/ p' "$FILE" >temp
或者
sed '/pattern1/,/pattern2/ !d' "$FILE" >temp
您可能不应该保留grep
管道,但这是为了补充一点,您可以将它们缩短为直接返回行号的东西sed
。
start=$( sed -n '/pattern1/ { =; q; }' )
上面将为您提供与模式匹配的第一行的行号pattern1
。它是=
输出当前行号的命令。
答案2
正如所讨论的,需要更改为双引号,但是如果文件具有超过一倍的模式,则原始脚本也会被破坏。上面的解决方案效果很好,只需打印开始/结束模式之间的每一行即可。此单行代码仅打印第一次出现的情况:
sed -n '/pattern1/{:loop;p;/pattern2/q;N;s/.*\n//;b loop};' "$file"