Bash 如何获取与正则表达式匹配的第一行之后的文件部分?
我有一个大约1000行的文件。我想要文件中与grep语句匹配的行后面的部分 即:Bash 如何获取与正则表达式匹配的第一行之后的文件部分?,bash,shell,scripting,grep,Bash,Shell,Scripting,Grep,我有一个大约1000行的文件。我想要文件中与grep语句匹配的行后面的部分 即: $ cat file | grep 'TERMINATE' # It is found on line 534 因此,我希望文件从第535行到第1000行进行进一步处理 如何才能做到这一点?使用bash参数展开,如下所示: content=$(cat file) echo "${content#*TERMINATE}" 作为一个简单的近似值,您可以使用 grep -A100000 TERMINATE f
$ cat file | grep 'TERMINATE' # It is found on line 534
因此,我希望文件从第535行到第1000行进行进一步处理
如何才能做到这一点?使用bash参数展开,如下所示:
content=$(cat file)
echo "${content#*TERMINATE}"
作为一个简单的近似值,您可以使用
grep -A100000 TERMINATE file
它greps表示终止
,并在该行之后输出多达100000行
从手册页
-A NUM,--after context=NUM
在匹配行之后打印尾随上下文的行数。 将包含组分隔符(--)的行放置在 连续的匹配组。使用-o或--only匹配 选项,则此选项无效,并发出警告
sed是一个更好的工作工具: sed-n'/re/,$p'文件 其中re是regexp
另一个选项是grep的--after上下文标志。您需要传入一个数字以结束,在文件上使用wc应该给出正确的停止值。将其与-n和匹配表达式结合使用。以下内容将打印匹配的行
终止
,直到文件结束:
sed -n -e '/TERMINATE/,$p'
tail -n "+$(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)" file
tail -n "+$(($(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)+1))" file
解释:-n
禁用sed
在其上执行脚本后打印每行的默认行为,-e
指示脚本到sed
,/TERMINATE/,$
是地址(行)范围选择,表示与TERMINATE
正则表达式匹配的第一行(如grep)到文件的末尾($
),而p
是打印当前行的打印命令
这将从匹配的行后面的行开始打印,直到文件结束:
(从匹配线后到EOF,不包括匹配线)
解释:1,/TERMINATE/
是一个地址(行)范围选择意味着输入到与TERMINATE
正则表达式匹配的第一行的第一行,而d
是删除当前行并跳到下一行的删除命令。由于sed
默认行为是打印行,它将在TERMINATE
结束后打印行输入的数量
编辑:
如果要在终止之前终止
:
sed -e '/TERMINATE/,$d'
如果您希望在一次传递中在两个不同的文件中终止前后的两行:
sed -e '1,/TERMINATE/w before
/TERMINATE/,$w after' file
before和after文件将包含带有terminate的行,因此要处理每一行,您需要使用:
head -n -1 before
tail -n +2 after
Edit2:
如果不想在sed脚本中硬编码文件名,可以:
before=before.txt
after=after.txt
sed -e "1,/TERMINATE/w $before
/TERMINATE/,\$w $after" file
但是您必须转义$
,这意味着最后一行,这样shell就不会尝试展开$w
变量(注意,我们现在在脚本周围使用双引号,而不是单引号)
我忘了告诉sed,在脚本中的文件名之后新行很重要,这样sed就知道文件名结束了
编辑:2016-0530
塞巴斯蒂安·克莱门特问:“你将如何用一个变量替换硬编码的TERMINATE
?”
您可以为匹配的文本创建一个变量,然后按照与上一个示例相同的方式执行此操作:
matchtext=TERMINATE
before=before.txt
after=after.txt
sed -e "1,/$matchtext/w $before
/$matchtext/,\$w $after" file
要将变量用于与前面示例匹配的文本,请执行以下操作:
## Print the line containing the matching text, till the end of the file:
## (from the matching line to EOF, including the matching line)
matchtext=TERMINATE
sed -n -e "/$matchtext/,\$p"
在这些情况下,用变量替换文本的要点是:
包含在单引号中的变量($variablename
)不会“展开”,但包含在双引号中的变量会“展开”。因此,如果它们包含要用变量替换的文本,则必须将所有单引号更改为双引号
sed
范围还包含一个$
,后面紧跟着一个字母,如:$p
、$d
、$w
。它们看起来也像要展开的变量,因此必须用反斜杠[\
转义这些$
字符例如:\$p
,\$d
,\$w
如果出于任何原因,您希望避免使用sed,以下内容将打印匹配的行TERMINATE
,直到文件结束:
sed -n -e '/TERMINATE/,$p'
tail -n "+$(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)" file
tail -n "+$(($(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)+1))" file
以下内容将从匹配终止的下一行打印到文件末尾:
sed -n -e '/TERMINATE/,$p'
tail -n "+$(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)" file
tail -n "+$(($(grep -n 'TERMINATE' file | head -n 1 | cut -d ":" -f 1)+1))" file
sed可以在一个进程中完成的工作需要两个进程,如果文件在执行grep和tail之间发生变化,结果可能不一致,因此我建议使用sed。此外,如果文件不包含TERMINATE
,第一个命令将失败。此处使用的工具是awk:
cat file | awk 'BEGIN{ found=0} /TERMINATE/{found=1} {if (found) print }'
这是如何工作的:
我们将变量“found”设置为零,计算结果为false
如果在正则表达式中找到“TERMINATE”的匹配项,则将其设置为1
如果“found”变量的计算结果为True,请打印:)
如果在非常大的文件上使用其他解决方案,可能会消耗大量内存。使用sed
或awk
有很多方法:
sed -n '/TERMINATE/,$p' file
这将在文件中查找终止
,并从该行打印到文件末尾
awk '/TERMINATE/,0' file
这与sed的行为完全相同
如果您知道要开始打印的行号,可以将其与NR
一起指定(记录号,它最终指示行号):
例子
如果我正确理解了您的问题,您确实希望在终止
之后的行,而不包括
终止
-行。awk
可以用一种简单的方式完成这项工作:
awk '{if(found) print} /TERMINATE/{found=1}' your_file
说明:
虽然不是最佳实践,但您可以依赖以下事实:所有变量默认为0或空的st
LINE_NUMBER=`grep -o -n TERMINATE $OSCAM_LOG|tail -n 1|sed "s/:/ \\'/g"|awk -F" " '{print $1}'`
tail -n +$LINE_NUMBER $YOUR_FILE_NAME