使用sed在文本文件中移动匹配行

时间:2019-03-13 17:19:20

标签: regex bash sed

我正在尝试关注该帖子

How to move specified line in file to other place with regexp match (bash script)?

到我的示例文件

asdasd0
-SRC_OUT_DIR = /a/b/c/d/e/f/g/h
asdasd2
asdasd3
asdasd4
DEFAULTS {
asdasd6

最终输出应为

asdasd0
asdasd2
asdasd3
asdasd4
DEFAULTS {
-SRC_OUT_DIR = /a/b/c/d/e/f/g/h
asdasd6

我尝试了以下

sed "/-SRC_OUT_DIR.*/d;/DEFAULTS { /a"$(sed -n '/-SRC_OUT_DIR.*/p' test.txt)  test.txt`

,但是它不起作用。我得到以下输出

sed:can't read =: No such file or directory
sed:can't read "/a/b/c/d/e/f/g": No such file or directory
asdasd0
asdasd2
asdasd3
asdasd4
DEFAULTS {
-SRC_OUT_DIR
asdasd6

我还想知道为什么我不能使用\1\2来打印需要移动的行。我试过了,但是什么也没打印。如果我需要将多条匹配的行移动到文件中的不同位置,该如何写sed命令?

2 个答案:

答案 0 :(得分:2)

您可以将匹配的行存储在hold空间中,delete,然后将append的保留空间存储到要插入的行之后:

$ sed '/^-SRC_OUT_DIR/{h;d;};/^DEFAULTS {/G' infile
asdasd0
asdasd2
asdasd3
asdasd4
DEFAULTS {
-SRC_OUT_DIR = /a/b/c/d/e/f/g/h
asdasd6

答案 1 :(得分:1)

当您提出sed解决方案时,我建议为此使用awk。 确实不建议使用大量sed命令的丑陋嵌套。尤其是因为您两次读取文件。

这是个awk

awk '/SRC_OUT_DIR/{t=$0;next}1;/DEFAULTS/{print t}' file

它如何工作?

awk将逐行读取您的file。每行,它将依次执行以下三个命令:

  1. /SRC_OUT_DIR/{t=$0;next}:如果该行包含与SRC_OUT_DIR匹配的子字符串,则将该行存储在变量t中并移至next行(不要执行2和3)
  2. 1默认操作:打印行
  3. /DEFAULTS/{print t} :如果当前行包含子字符串DEFAULTS,则打印存储在变量t中的行

如果要移动多行(只会向下移动):

awk '/pattern1/ {t[1]=$0;next}
     /pattern2/ {t[2]=$0;next}
     /pattern3/ {t[3]=$0;next}
     /target3/ { print t[3] }
     1
     /target1/ { print t[1] }
     /target2/ { print t[2] }' file

请注意,pattern3将在target3之前打印。