我有一个文件:users.txt,如下所示:
Surname
Surname
Surname
Age
Age
Age
我需要添加带有文字的 ONE 行:Name
ABOVE ,无论我在哪里找到{{1>}的 FIRST 这样文件看起来像:
Surname
我还需要能够在文本中添加 ONE 一行: Name
Surname
Surname
Surname
Age
Age
Age
BELOW ,无论我在哪里找到 LAST Gender
以便文件如下:
Age
目前我有这些sed命令:
Surname
Surname
Surname
Age
Age
Age
Gender
虽然他们在找到 EVERY 匹配项时添加了新行。
非常感谢您的时间和帮助。
答案 0 :(得分:4)
file=users.txt
tmpfile=$(mktemp)
tac "$file" |
awk '/Age/ && !found {print "Gender"; found=1} 1' |
tac |
awk '/Surname/ && !found {print "Name"; found=1} 1' > "$tmpfile" &&
mv "$tmpfile" "$file"
实际上sed不是那么残暴:
sed '
/Surname/ {
# we have seen the first pattern, insert the 1st new line
i Name
:a
N # append the next line to pattern space
$ { # if this is the last line
s/.*Age\n/&Gender\n/ # add the 2nd new line after the last Age
bb # and we are done: goto b
}
ba # goto a
:b
}
' users.txt
答案 1 :(得分:1)
使用awk:
awk '/Surname/ && !s++ { print "Name" } /Age/ { a = 1; print; next } a && !f++ { print "Gender" } 1; END { if(a && !f) { print "Gender" } }' filename
其工作原理如下:
/Surname/ && !s++ { # If Surname is found in a line and the flag for it
# is not set (i.e., if this is the first surname line),
# set flag and
print "Name" # print "Name"
}
/Age/ { # if Age is found
a = 1 # set flag for it
print # print the line
next # and do nothing else for this line
}
a && !f++ { # if the Age flag is set and (implicitly here) Age
# is not found in the line, and the flag that we
# already did this is not yet set, set the flag, and
print "Gender" # print Gender
}
1 # then, finally, print the line from the input.
END { # if we reach the end without having printed the
if(a && !f) { # gender line but found an Age block (that is, when the
# age block is at the end of the file)
print "Gender" # print it then.
}
}
!s++
内容是一种检查标志是否未设置并一次性设置的方法;我被告知这是惯用的awk。如果您对此感到不舒服,也可以写
/Surname/ && !s { s = 1; print "Name" }
等具有相同的效果。
答案 2 :(得分:1)
有很多方法可以做到这一点,但我喜欢的方法是坚固性,灵活性,清晰度,简单性,缺乏代码重复等,一次确定目标线,然后在第二次使用它们通过:
gawk '
NR==FNR { if (!first[$0]) first[$0]=NR; last[$0]=NR; next }
FNR==first["Surname"] { print "Name" }
{ print }
FNR==last["Age"] { print "Gender" }
' file file
答案 3 :(得分:1)
如何在Perl中执行此操作
perl -nE'/Surname/&&($n++||say"Name")||($n=0);/Age/&&($g=1)||($g--&&say"Gender");print}{say"Gender"if$g'
另一种方式
perl -nE'/Surname/&&say("Name")..!/Surname/;/Age/&&($g=1)||($g--&&say"Gender");print}{say"Gender"if$g'
答案 4 :(得分:1)
这是如何在最后一次匹配之前插入带有 sed 的行。
sed -i -e '/**PATTERN**[^\n]*/,$!b;//{x;//p;g};//!H;$!d;x;i**TEXTOINSERT**' FILE
这是如何在第一次匹配之前用 sed 插入一行。
sed -i -e '/**PATERN**/{a\\**TEXTOINSERT**' -e ':a;n;ba}' FILE
答案 5 :(得分:0)
awk中
设置Surname第一次出现的记录编号和最后一次出现的年龄,读取文件两次并在达到设定的记录编号时打印。
awk '/Surname/ && !s++{Sr=NR}/Age/{FNR==NR&&age=NR}
FNR!=NR{print (Sr==FNR?"Name\n"$0:age==FNR?$0"\nGender":$0)}' test{,}
Name
Surname
Surname
Surname
Age
Age
Age
Gender