Yug*_*dle 163 bash shell scripting grep
我有一个大约1000行的文件.我希望我的文件的一部分在与我的grep语句匹配的行之后.
即
$ cat file | grep 'TERMINATE' # It is found on line 534
Run Code Online (Sandbox Code Playgroud)
所以,我希望该行文件__CODE__
可以进一步处理.
我该怎么做 ?
jfg*_*956 296
以下将打印匹配TERMINATE
到文件末尾的行:
sed -n -e '/TERMINATE/,$p'
Run Code Online (Sandbox Code Playgroud)
解释: -n
禁用sed
在执行其脚本后打印每一行的默认行为,-e
表示脚本为sed
,/TERMINATE/,$
是一个地址(行)范围选择,意味着第一行匹配TERMINATE
正则表达式(如grep)到文件末尾($
) ,p
是打印当前行的打印命令.
这将从行匹配后的行打印TERMINATE
到文件末尾:(
从匹配行到EOF之后,不包括匹配行)
sed -e '1,/TERMINATE/d'
Run Code Online (Sandbox Code Playgroud)
解释: 1,/TERMINATE/
是一个地址(行)范围选择,意味着第一行输入到匹配TERMINATE
正则表达式的第一行,d
是删除当前行并跳到下一行的删除命令.由于sed
默认行为是打印线,将打印的行后TERMINATE
输入结束.
编辑:
如果你想要之前的行TERMINATE
:
sed -e '/TERMINATE/,$d'
Run Code Online (Sandbox Code Playgroud)
如果你想TERMINATE
在一次传递中在2个不同的文件中前后两行:
sed -e '1,/TERMINATE/w before
/TERMINATE/,$w after' file
Run Code Online (Sandbox Code Playgroud)
before和after文件将包含具有terminate的行,因此要处理每个需要使用的行:
head -n -1 before
tail -n +2 after
Run Code Online (Sandbox Code Playgroud)
EDIT2:
如果您不想在sed脚本中对文件名进行硬编码,则可以:
before=before.txt
after=after.txt
sed -e "1,/TERMINATE/w $before
/TERMINATE/,\$w $after" file
Run Code Online (Sandbox Code Playgroud)
但是你必须逃避$
最后一行的含义,所以shell不会尝试扩展$w
变量(注意我们现在使用脚本周围的双引号而不是单引号).
我忘了告诉新行在脚本中的文件名之后很重要,以便sed知道文件名结束.
编辑: 2016-0530
SébastienClément问道:"你怎么TERMINATE
用变量取代硬编码?"
您可以为匹配的文本创建一个变量,然后以与上一个示例相同的方式执行此操作:
matchtext=TERMINATE
before=before.txt
after=after.txt
sed -e "1,/$matchtext/w $before
/$matchtext/,\$w $after" file
Run Code Online (Sandbox Code Playgroud)
使用变量作为匹配文本与前面的示例:
## 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"
Run Code Online (Sandbox Code Playgroud)
## Print from the line that follows the line containing the
## matching text, till the end of the file:
## (from AFTER the matching line to EOF, NOT including the matching line)
matchtext=TERMINATE
sed -e "1,/$matchtext/d"
Run Code Online (Sandbox Code Playgroud)
## Print all the lines before the line containing the matching text:
## (from line-1 to BEFORE the matching line, NOT including the matching line)
matchtext=TERMINATE
sed -e "/$matchtext/,\$d"
Run Code Online (Sandbox Code Playgroud)
在这些情况下,用变量替换文本的重点是:
$variablename
包含在single quotes
[ '
]中的变量()不会"展开",而是double quotes
[ "
]中的变量.因此,如果它们包含要用变量替换的文本single quotes
,double quotes
则必须更改所有to . sed
范围也包含$
并紧跟像字母:$p
,$d
,$w
.他们也将像变量加以扩展,所以你要逃避这些$
字符用反斜杠[ \
],如:\$p
,\$d
,\$w
.aio*_*obe 61
作为一个简单的近似,你可以使用
grep -A100000 TERMINATE file
Run Code Online (Sandbox Code Playgroud)
它会在该TERMINATE
行之后输出并输出多达100000行.
从手册页
-A NUM, --after-context=NUM
匹配行后打印NUM行尾随上下文. 在连续的匹配组之间放置一个包含组分隔符( - )的行.使用-o或--only-matching选项,这不起作用,并给出警告.
小智 26
这里使用的工具是awk:
cat file | awk 'BEGIN{ found=0} /TERMINATE/{found=1} {if (found) print }'
Run Code Online (Sandbox Code Playgroud)
这是如何运作的:
如果您在非常大的文件上使用它们,其他解决方案可能会占用大量内存.
如果我正确地理解了你的问题,你确实想要后面 的行TERMINATE
,不包括TERMINATE
-line.awk
可以这么简单地做到这一点:
awk '{if(found) print} /TERMINATE/{found=1}' your_file
Run Code Online (Sandbox Code Playgroud)
说明:
if(found) print
)不会打印任何东西.这将打印-line 之后的所有行TERMINATE
.
概括:
例:
$ cat ex_file.txt
not this line
second line
START
A good line to include
And this line
Yep
END
Nope more
...
never ever
$ awk '/END/{found=0} {if(found) print} /START/{found=1}' ex_file.txt
A good line to include
And this line
Yep
$
Run Code Online (Sandbox Code Playgroud)
说明:
found
已设置,则打印当前行.found=1
线,则设置为打印以下行.请注意,此检查在实际打印后完成,以从结果中排除起始线.笔记:
BEGIN{found=0}
在awk-expression的开头添加一个.使用bash参数扩展,如下所示:
content=$(cat file)
echo "${content#*TERMINATE}"
Run Code Online (Sandbox Code Playgroud)
小智 6
grep -A 10000000 '终止' 文件
有很多方法可以使用sed
or来做到这一点awk
:
sed -n '/TERMINATE/,$p' file
Run Code Online (Sandbox Code Playgroud)
这会在您的文件中查找TERMINATE
并从该行打印到文件末尾。
awk '/TERMINATE/,0' file
Run Code Online (Sandbox Code Playgroud)
这与以下行为完全相同sed
。
如果您知道要开始打印的行号,则可以将其与NR
(记录数,最终指示行号)一起指定:
awk 'NR>=535' file
Run Code Online (Sandbox Code Playgroud)
$ seq 10 > a #generate a file with one number per line, from 1 to 10
$ sed -n '/7/,$p' a
7
8
9
10
$ awk '/7/,0' a
7
8
9
10
$ awk 'NR>=7' a
7
8
9
10
Run Code Online (Sandbox Code Playgroud)