问题描述
我有一个看起来像这样的文本文件
1
bbbbb
aaa
END
2
ttttt
mmmm
uu
END
3
....
END
单个数字模式(1,2,3)和END之间的行数是可变的。因此上限定界模式会发生变化,但最后一个定界模式不会发生变化。使用一些bash命令,我想在指定的上一个伙伴和对应的END之间grep行,例如,一个将输入2作为输入并返回
的命令。 2
ttttt
mmmm
uu
END
我已经用sed和awk尝试了各种解决方案,但仍然无法解决。主要问题是我可能需要在文件中间添加一个条目,因此我不能将sed与/ pattern / q一起使用...任何帮助将不胜感激!
解决方法
使用awk
,我们在匹配作为输入参数的开始模式时设置了一个标志f
。在该行之后,该标志将打开,并打印每一行。当到达“ END”(并且该标志处于打开状态!)时,它退出。
awk -v p=2 '$0~p{f=1} f{print} f&&/END/{exit}' file
,
使用sed及其地址仅在模式之间打印文件的一部分:
#!/bin/bash
start=x
while [[ $start = *[^0-9]* ]] ; do
read -p 'Enter the start pattern: ' start
done
sed -n "/^$start$/,/^END$/p" file
,
您可以将sed
与地址范围一起使用。为方便起见,修改RE1
中的第一个正则表达式(/RE1/,/RE2/
):
sed -n '/^[[:space:]]*2$/,/^[[:space:]]*END$/p' file
或者,
sed '
/^[[:space:]]*2$/,/^[[:space:]]*END$/!d
/^[[:space:]]*END$/q
' file
这会在读取END
后退出,因此可能更有效。
仅使用bash
#!/usr/bin/env bash
start=$1
while IFS= read -r lines; do
if [[ ${lines##* } == $start ]]; then
print=on
elif [[ ${lines##* } == [0-9] ]]; then
print=off
fi
case $print in on) printf '%s\n' "$lines";; esac
done < file.txt
以数字作为参数运行脚本,1可以2或3或...
./myscript 1
,
这可能对您有用(GNU sed):
sed -n '/^\s*2$/{:a;N;/^\s*END$/M!ba;p;q}' file
通过设置-n
选项关闭隐式打印。
聚集以2
开头的行和以END
开头的行的行,打印集合并退出。
第二个正则表达式使用M
标志,当多行被匹配时,它允许^
和$
匹配行的开始和结束。要记住的另一件事是,使用范围sed -n '/start/,/end/p' file
将在满足第一个条件时开始打印行,如果第二个匹配不成立,它将继续打印到文件末尾。 / p>