Shell 搜索一个字符串并替换搜索字符串上方的另一个字符串
我有一个下面几行的文件Shell 搜索一个字符串并替换搜索字符串上方的另一个字符串,shell,awk,sed,Shell,Awk,Sed,我有一个下面几行的文件 123 456 123 789 abc efg xyz 我需要用abc搜索,并用111替换前面的123。这是要求,abc在文件中仅出现一次,但123可以多次出现,并且123可以位于abc上方的任何位置。 请帮帮我 我试过用下面的命令 sed -i.bak "/abc/!{x;1!p;d;};x;s/123/1111" filename 使用上面的命令,它只替换123,如果123刚好在abc上方,如果123在abc上方两行,则替换失败。要做的不止这些。这里有一个: se
123
456
123
789
abc
efg
xyz
我需要用abc
搜索,并用111
替换前面的123
。这是要求,abc
在文件中仅出现一次,但123
可以多次出现,并且123可以位于abc
上方的任何位置。
请帮帮我
我试过用下面的命令
sed -i.bak "/abc/!{x;1!p;d;};x;s/123/1111" filename
使用上面的命令,它只替换
123
,如果123
刚好在abc
上方,如果123
在abc
上方两行,则替换失败。要做的不止这些。这里有一个:
sed -i.bak '1{h;d;};/123/{x;p;d;};/abc/{x;s/123/111/;p;d;};H;${x;p;};d' filename
要做到这一点,还有很多事情要做。这里有一个:
sed -i.bak '1{h;d;};/123/{x;p;d;};/abc/{x;s/123/111/;p;d;};H;${x;p;};d' filename
ed
对于复杂的脚本文件编辑非常方便:
ed -s file <<EOF
/^abc$/;?^123$?;.c
111
.
w
EOF
ed-s文件ed
对于复杂的脚本文件编辑非常方便:
ed -s file <<EOF
/^abc$/;?^123$?;.c
111
.
w
EOF
ed-s文件这可能适合您(GNU-sed):
这会将文件读入内存,并在abc
之前最后出现的123
前面插入111
内存占用较少的解决方案:
sed -E '/^123$/{:a;N;/\n123$/{h;s///p;g;s/.*\n//;ba};/\nabc$/!ba;s/^/111\n/}' file
这将在包含123
的行之后收集行。如果遇到另一条包含123
的线路,它会卸载之前的所有线路,并再次开始收集线路。如果它发现一行包含abc
,它将在迄今为止收集的行的前面插入111
另一种选择:
sed '/abc/{x;/./{s/^/111\n/p;z};x;b};/123/{x;/./p;x;h;$!d;b};x;/./{x;H;$!d};x' file
这可能适用于您(GNU-sed):
这会将文件读入内存,并在abc
之前最后出现的123
前面插入111
内存占用较少的解决方案:
sed -E '/^123$/{:a;N;/\n123$/{h;s///p;g;s/.*\n//;ba};/\nabc$/!ba;s/^/111\n/}' file
这将在包含123
的行之后收集行。如果遇到另一条包含123
的线路,它会卸载之前的所有线路,并再次开始收集线路。如果它发现一行包含abc
,它将在迄今为止收集的行的前面插入111
另一种选择:
sed '/abc/{x;/./{s/^/111\n/p;z};x;b};/123/{x;/./p;x;h;$!d;b};x;/./{x;H;$!d};x' file
这是一个典型的情况,您可以跟踪上一行并根据满足当前行的条件更改内容。通常,awk程序如下所示:
awk '(FNR==1){prev=$0; next}
(condition_on_$0) { action_on_prev }
{ print prev; prev = $0 }
END { print $0 }'
因此,在OP的情况下,这将是:
awk '(FNR==1){prev=$0; next}
$0 == "abc" { if (prev == "123") prev = "111" }
{ print prev; prev = $0 }
END { print $0 }'
这是一个典型的情况,您可以跟踪上一行并根据满足当前行的条件更改内容。通常,awk程序如下所示:
awk '(FNR==1){prev=$0; next}
(condition_on_$0) { action_on_prev }
{ print prev; prev = $0 }
END { print $0 }'
因此,在OP的情况下,这将是:
awk '(FNR==1){prev=$0; next}
$0 == "abc" { if (prev == "123") prev = "111" }
{ print prev; prev = $0 }
END { print $0 }'
感谢您的帮助,这是可行的,但是当我使用变量作为“abc”时,变量替换失败了
var=abc sed-I.bak'1{h;d;}/123/{x;p;d;}/${var}/{x;s/123/111/;p;d;};H${x;p;};d'filename@kiranpaila:请尝试使用sed“…$var…”
(注意双引号和缺少括号)。如何使用下面的命令仅搜索替换sed-i.bak'1{h;d;}的以上5行/123/{x;p;d;}/abc/{x;s/123/111/;p;d;};H${x;p;};d'filename只需要检查前面几行来替换,而不是检查前面所有的行谢谢帮助,这是可行的,但是当我使用变量来“abc”时,变量替换失败了
var=abc sed-I.bak'1{h;d;}/123/{x;p;d;}/${var}/{x;s/123/111/;p;d;};H${x;p;};d'filename@kiranpaila:请尝试使用sed“…$var…”
(注意双引号和缺少括号)。如何使用下面的命令仅搜索替换sed-i.bak'1{h;d;}的以上5行/123/{x;p;d;}/abc/{x;s/123/111/;p;d;};H${x;p;};d’filename只需检查前几行即可替换,而不必检查前几行