sed条件匹配并执行带偏移的命令

时间:2019-04-28 00:49:36

标签: bash sed replace

我正在寻找一个bash命令,以有条件的替换offset。我发现的现有帖子是有条件替换没有偏移或带有固定偏移。

任务:如果uid包含8964,则在FORBIDDEN之前插入行DOB

下面的每个TXT文件代表一个用户,并且包含(按以下顺序)

  1. 一些属性
  2. 唯一 uid
  3. 一些质量
  4. 唯一 DOB
  5. 随机的 lorem ipsum

希望我可以转换以下文件

# file1.txt (uid doens't match 8964)
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako

# file2.txt (uid matches 8964)
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
DOB: 1234-05-06
saadi torem lopez dupont

进入

# file1.txt (uid doens't match 8964)
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako

# file2.txt (uid matches 8964)
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
FORBIDDEN
DOB: 1234-05-06
saadi torem lopez dupont

我的尝试:

如果uid包含8964,则与DOB进行第二次匹配,并在FORBIDDEN上方插入DOB

sed '/^uid: [0-9]*8964[0-9]*$/{n;/^DOB: .*$/{iFORBIDDEN}}' file*.txt

这给了我无与伦比的{错误。

sed: -e expression #1, char 0: unmatched `{'

我知道如果sed '/PAT/{n;p}'{n;p}匹配,PAT将执行/PAT2/{iTEXT},但是似乎无法将/PAT/{ }放在FORBIDDEN内。

如何执行{{1}}插入?

3 个答案:

答案 0 :(得分:2)

$ awk '
  /^uid/ && /8964/ {f=1}                     #1
  /^DOB/ && f {print "FORBIDDEN"; f=0}       #2
  1                                          #3
' file
  1. 如果以“ uid”开头的行与“ 8964”匹配,则设置标志
  2. 如果一行以“ DOB”开头并且设置了标志,则打印字符串和未设置标志
  3. 打印每一行
$ awk -v RS='' '/uid: [0-9]*8964/{sub(/DOB/, "FORBIDDEN\nDOB")} 1' file

或者,将由空行分隔的每个块都视为一条记录,然后在匹配的情况下在“ FORBIDDEN \ nDOB”中进行查找。我认为第一个更好的做法。作为一个非常普遍的规则,一旦您开始考虑字段/记录,就该开始使用awk / perl。

答案 1 :(得分:1)

我认为,这是sed的好用例。

以下是带有一些解释的GNU sed解决方案:

# script.sed
/^uid:.*8964/,/DOB/ { # Search only inside this range, if it exists.
  /DOB/i FORBIDDEN    # Insert FORBIDDEN before the line matching /DOB/.
}

测试:

▶ gsed -f script.sed FILE2 
citizen: true
hasSEAcct: true
uid: 289641
joyful hearty
final debug Juno XYus
magazine
FORBIDDEN
DOB: 1234-05-06
saadi torem lopez dupont
▶ gsed -f script.sed FILE1
admin: false
uid: 123456
happy
movie
DOB: 6543-02-10
lorem ipsum
seo varis lireccuni paccem noba sako

或一行:

▶ gsed -e '/^uid:.*8964/,/DOB/{/DOB/i FORBIDDEN' -e '}' FILE*

答案 2 :(得分:1)

在gnu sed上尝试

 sed -Ee '/^uid:\s*\w*8964\w*$/{n;/^DOB:/iFORBIDDEN' -e '}' file*.txt