我有一个可变的输入文件,其格式可以如下。
text1 valueA valueN valueB
text2 valueX
text1 valueC valueN valueD
text2 valueX
text1 valueE valueM valueF
text1 valueG valueM valueH
text1 valueI valueN valueJ
text2 valueX
text1 valueK valueO valueL
text1 valueP valueO valueQ
text1 valueR valueN valueS
text1 valueT valueM valueU
我只想打印text1 valueA valueN valueB
在上一行的下面。例如,输出应为:
text2 valueX
我还需要匹配text1 valueA valueN valueB
text2 valueX
text1 valueC valueN valueD
text2 valueX
text1 valueI valueN valueJ
text2 valueX
的一部分。假设valueX
,我需要匹配valueX=a.b.c.d-e
a.b.
更新: 抱歉,输入数据不清楚...我想我可以匹配部分文本,但是我错了。
因此,如果数据看起来像这样:
myvariable=a.b.
echo $myvariable
a.b.
如果text1 valueA valueN valueB
text2 a.b.c.d-e
text1 valueC valueN valueD
text2 a.b.c.d-e
text1 valueE valueM valueF
text1 valueG valueM valueH
text1 valueI valueN valueJ
text2 a.b.c.d-e
text1 valueK valueO valueL
text1 valueP valueO valueQ
text1 valueR valueN valueS
text1 valueT valueM valueU
,则如何匹配a.b.
val=a.b.
答案 0 :(得分:2)
这是awk中的一个:
$ awk '$0=="text2 valueX"{print p ORS $0}{p=$0}' file
输出:
text1 valueA valueN valueB
text2 valueX
text1 valueC valueN valueD
text2 valueX
text1 valueI valueN valueJ
text2 valueX
解释:
$ awk '
$0=="text2 valueX" { # if record is a match
print p ORS $0 # print previous buffered record and current
}
{
p=$0 # buffer record for next round
}' file
更新的更新,其中包含更新的数据:
由于.
是正则表达式元字符,因此需要在输入时对其进行转义以避免与abbb
匹配:
$ awk -v s="a\\\.b\\\." '$0~s{print p ORS $0}{p=$0}' file
现在输出:
text1 valueA valueN valueB
text2 a.b.c.d-e
text1 valueC valueN valueD
text2 a.b.c.d-e
text1 valueI valueN valueJ
text2 a.b.c.d-e
答案 1 :(得分:1)
使用tac
和awk
的另一种简单方法。
tac Input_file | awk '$0=="text2 valueX"{print;getline;print}' | tac
输出如下。
text1 valueA valueN valueB
text2 valueX
text1 valueC valueN valueD
text2 valueX
text1 valueI valueN valueJ
text2 valueX
strace
中有一些tac
(用于处理任意文件):
lseek(3, 351051776, SEEK_SET) = 351051776
read(3, "83,10.1579,56.1257,1412067900\n41"..., 8192) = 8192
write(1, "104,210,84,194,10.1313,56.1528,1"..., 4096) = 4096
write(1, "2092,56.1724,1412068200\n129,20,3"..., 4096) = 4096
lseek(3, 351043584, SEEK_SET) = 351043584
read(3, "7900\n148,159,77,186,97,10.2090,5"..., 8192) = 8192
write(1, ",140,182,10.1208,56.1784,1412067"..., 4096) = 4096
write(1, "10.1859,56.1239,1412067900\n53,17"..., 4096) = 4096
lseek(3, 351035392, SEEK_SET) = 351035392
您可以在lseek
中看到递减的位置。
答案 2 :(得分:1)
尝试一下:
awk 'NR>1&& $0 == "text2 valueX"{print a"\n"$0} {a=$0}' input.txt
请注意,仅当当前行与'text2 valueX'完全匹配时,此脚本才会打印某些内容。
答案 3 :(得分:1)
一种sed
解决方案:
$ sed -n -e '/text2 valueX/{' -e 'H;x;p;}' -e 'h' file
text1 valueA valueN valueB
text2 valueX
text1 valueC valueN valueD
text2 valueX
text1 valueI valueN valueJ
text2 valueX
如果要匹配整行,请将正则表达式更改为/^text2 valueX$/
。
它等于GNU sed的:
sed -n '/text2 valueX/{H;x;p;};h' file
POSIX sed
需要在-e
左括号或{
右括号之后开始换行或新的}
块。
H Append the contents of pattern space to hold space, separate them by a newline character.
x Exchange the contents of pattern space and hold space.
p Print the contents of pattern space.
h Overwrite the contents of hold space with pattern space.
/text2 valueX/
是正则表达式,它与当前行(模式空间)匹配,如果匹配,则将执行该命令或{}
块。
在块内,添加行以保留空间,该空间已包含最后一行。然后将保留空间与图案空间交换,然后进行打印。
在该块之后,将当前行推入容纳空间以替换其先前的内容。
注意:使用此解决方案,您不能连续多行text2 valueX
,否则它将打印多余的行。如果发生这种情况,请发表评论,让我知道您想如何与他们打交道。
答案 4 :(得分:0)
这可能对您有用(GNU sed):
sed '$!N;/\ntext2 valueX/p;D' file
在文件的整个长度上打开两行移动的窗口。
如果第二行与text2 valueX
相匹配,则打印两行。
删除第一行并重复。
对于已更改的问题:
sed '$!N;/\ntext2.*a\.b\./p;D' file
使用相同的方法,但引入新的模式作为正则表达式。
新模式可能需要用引号引起来,例如该时间段必须以\
开头。
regexp='a\.b\.'
sed '$!N;/\ntext2.*'"$regexp"'/p;D' file