预制 sed 字符串无法正确解释字符串

预制 sed 字符串无法正确解释字符串

我的代码旨在查找一个文件中的行号,其中两个不同的文件是等效的,然后从其中一个文件中删除除这些行号之外的所有行号。为此,我制作了一个预制的 sed 字符串,我想在 sed 中运行,但出现错误:

sed: -e expression #1, char 3: unknown command: `;'

我的预制 sed 字符串看起来像这样

echo ${_sedstr}
1;2;7;11;12;13;15;17;22!d

我的目的是在 sed 命令中使用此变量来删除文件 ${_edit} 中除字符串中的行之外的所有行

sed -i.bak -e ${_sedstr} ${_edit} 

我已经尝试了在 ${_sedstr} 周围放置单/双引号并使用反斜杠“\”转义引号的所有组合,但我似乎仍然对按预期运行的代码存在问题。


我想要实现的一个例子是 ${_edit} 看起来像这样:

hello
my
name
is
John
Doe

使用表达式sed -i.bak -e '1;2;4!d' ${_edit},我希望文件输出到

hello
my
is

删除除 1、2 和 4 之外的所有行。

答案1

这不是正确的sed语法。

应该sed '1d;2d;7d'不是sed '1;2;7d'

要删除除 1、2、7 之外的所有命令,请使用sed -e 1b -e 2b -e 7b -e d(您不能使用可移植/POSIXly 来;分隔b命令,但可以使用换行符)。

所以:

sed_script='1d;2d;7d'
sed -i.back -e "$sed_script" -- "$_edit"

或者:

sed_script='
  1b
  2b
  7b
  d
'
sed -i.back -e "$sed_script" -- "$_edit"

参数扩展应该被引用。看什么时候需要双引号?。并且不要忘记--选项分隔符。就是cmd -- "$arg",你不想要cmd "$option_or_arg"这里。

对于要保留/删除的大量行,使用 GNU awk,您可以使用:

LINES_TO_KEEP='1;2;7;...' gawk -i /usr/share/awk/inplace.awk -e '
  BEGIN {
    split(ENVIRON["LINES_TO_KEEP"], a, ";")
    for (i in a) keep[a[i]]
  }
  FNR in keep' -E /dev/null "$_edit"

(该文件不适用于名为 的文件-;您必须使用_edit=./-而不是_edit=-)。

不使用-i inplaceas尝试首先从当前工作目录gawk加载inplace扩展(asinplace或),有人可能已经在其中植入了恶意软件。随系统提供的扩展inplace.awk的路径可能会有所不同,请参阅输出inplacegawkgawk 'BEGIN{print ENVIRON["AWKPATH"]}'

答案2

有点偏离滑雪道sed,但既然已经回答了......如果你不担心顺序,只担心相同的配对线,你可以......

join <(sort file1) <(sort file2) > matchedlines

不需要了解行号,也不需要将数组传递到awk.

相关内容