我正在寻找一个bash命令,以有条件的替换offset。我发现的现有帖子是有条件替换没有偏移或带有固定偏移。
任务:如果uid
包含8964
,则在FORBIDDEN
之前插入行DOB
。
下面的每个TXT文件代表一个用户,并且包含(按以下顺序)
uid
DOB
希望我可以转换以下文件
# 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}}插入?
答案 0 :(得分:2)
$ awk '
/^uid/ && /8964/ {f=1} #1
/^DOB/ && f {print "FORBIDDEN"; f=0} #2
1 #3
' file
$ 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