我的代码旨在查找一个文件中的行号,其中两个不同的文件是等效的,然后从其中一个文件中删除除这些行号之外的所有行号。为此,我制作了一个预制的 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 inplace
as尝试首先从当前工作目录gawk
加载inplace
扩展(asinplace
或),有人可能已经在其中植入了恶意软件。随系统提供的扩展inplace.awk
的路径可能会有所不同,请参阅输出inplace
gawk
gawk 'BEGIN{print ENVIRON["AWKPATH"]}'
答案2
有点偏离滑雪道sed
,但既然已经回答了......如果你不担心顺序,只担心相同的配对线,你可以......
join <(sort file1) <(sort file2) > matchedlines
不需要了解行号,也不需要将数组传递到awk
.