Bash、grep在具有指定字符串的两行之间

时间:2022-05-15 21:45:50

Example:

例子:

a43
test1
abc
cvb
bnm
test2
kfo

I need all lines between test1 and test2. Normal grep does not work in this case. Do you have any propositions?

我需要test1和test2之间的所有行。在这种情况下,普通grep不起作用。你有什么建议吗?

8 个解决方案

#1


42  

Her are some awk These will print from test1 to test2

她是一些awk这些将打印从test1到test2

awk '/test1/{f=1} /test2/{f=0;print} f'
awk '/test1/{f=1} f; /test2/{f=0}' 
awk '/test1/,/test2/'

test1
abc
cvb
bnm
test2

These prints data between test1 to test2

这些数据在test1到test2之间打印数据。

awk '/test1/{f=1;next} /test2/{f=0} f' 
awk '/test2/{f=0} f; /test1/{f=1}' 

abc
cvb
bnm

#2


33  

You could use sed:

您可以使用sed:

sed -n '/test1/,/test2/p' filename

In order to exclude the lines containing test1 and test2, say:

为了排除包含test1和test2的行,例如:

sed -n '/test1/,/test2/{/test1/b;/test2/b;p}' filename

#3


7  

If you can only use grep:

如果您只能使用grep:

grep -A100000 test1 file.txt | grep -B100000 test2 > new.txt

grep -A and then a number gets the lines after the matching string, and grep -B gets the lines before the matching string. The number, 100000 in this case, has to be large enough to include all lines before and after.

grep -A,然后一个数字获取匹配字符串后面的行,grep -B获取匹配字符串前面的行。在这种情况下,100000这个数字必须足够大,足以包括前后的所有行。

If you don't want to include test1 and test2, then you can remove them afterwards by grep -v, which prints everything except the matching line(s):

如果您不想包含test1和test2,那么您可以在之后通过grep -v删除它们,它将打印除匹配行之外的所有内容:

egrep -v "test1|test2" new.txt > newer.txt

or everything in one line:

或者一切都在一行:

grep -A100000 test1 file.txt | grep -B100000 test2 | egrep -v "test1|test2" > new.txt 

#4


5  

Yep, normal grep won't do this. But grep with -P parameter will do this job.

是的,正常的grep不会这么做。但是带-P参数的grep将完成这项工作。

$ grep -ozP '(?s)test1\n\K.*?(?=\ntest2)' file
abc
cvb
bnm

\K discards the previously matched characters from printing at the final and the positive lookahead (?=\ntest2) asserts that the match must be followed by a \n newline character and then test2 string.

\K丢弃了在期末打印时之前匹配的字符,而积极的lookahead (?=\ntest2)断言匹配之后必须有一个\n个换行字符,然后是test2字符串。

#5


0  

The following script wraps up this process. More details in this similar * post

下面的脚本将结束这个过程。更多细节在这类似的堆栈溢出邮件。

get_text.sh

function show_help()
{
  HELP=$(doMain $0 HELP)
  echo "$HELP"
  exit;
}

function doMain()
{
  if [ "$1" == "help" ]
  then
    show_help
  fi
  if [ -z "$1" ]
  then
    show_help
  fi
  if [ -z "$2" ]
  then
    show_help
  fi

  FILENAME=$1
  if [ ! -f $FILENAME ]; then
      echo "File not found: $FILENAME"
      exit;
  fi

  if [ -z "$3" ]
  then
    START_TAG=$2_START
    END_TAG=$2_END
  else
    START_TAG=$2
    END_TAG=$3
  fi

  CMD="cat $FILENAME | awk '/$START_TAG/{f=1;next} /$END_TAG/{f=0} f'"
  eval $CMD
}

function help_txt()
{
HELP_START
  get_text.sh: extracts lines in a file between two tags

  usage: FILENAME {TAG_PREFIX|START_TAG} {END_TAG}

  examples:
    get_text.sh 1.txt AA     => extracts lines in file 1.txt between AA_START and AA_END
    get_text.sh 1.txt AA BB  => extracts lines in file 1.txt between AA and BB
HELP_END
}

doMain $*

#6


0  

You can do something like this too. Lets say you this file test.txt with content:

你也可以这样做。假设您进行了这个文件测试。txt和内容:

a43
test1
abc
cvb
bnm
test2
kfo

You can do

你可以做

cat test.txt | grep -A10 test1 | grep -B10 test2

猫测试。txt | grep -A10 test1 | grep -B10 test2

where -A<n> is to get you n lines after your match in the file and -B<n> is to give you n lines before the match. You just have to make sure that n > number of expected lines between test1 and test2. Or you can give it large enough to reach EOF.

其中-A 在文件中匹配后得到n行,-B 在匹配前得到n行。您只需确保test1和test2之间的预期行数为n >。或者你也可以给它足够大的空间。

Result:

结果:

test1
abc
cvb
bnm
test2

#7


0  

The answer by PratPor above:

以上PratPor的回答:

cat test.txt | grep -A10 test1 | grep -B10 test2

is cool.. but if you don't know the file length:

很酷. .但如果你不知道文件的长度:

cat test.txt | grep -A1000 test1 | grep -B1000 test2

Not deterministic, but not too bad. Anyone have better (more deterministic)?

不确定性,但不太坏。谁有更好的(更确定性的)?

#8


-3  

awk '/test1/,/test2/' filename.txt > outputFile.txt

#1


42  

Her are some awk These will print from test1 to test2

她是一些awk这些将打印从test1到test2

awk '/test1/{f=1} /test2/{f=0;print} f'
awk '/test1/{f=1} f; /test2/{f=0}' 
awk '/test1/,/test2/'

test1
abc
cvb
bnm
test2

These prints data between test1 to test2

这些数据在test1到test2之间打印数据。

awk '/test1/{f=1;next} /test2/{f=0} f' 
awk '/test2/{f=0} f; /test1/{f=1}' 

abc
cvb
bnm

#2


33  

You could use sed:

您可以使用sed:

sed -n '/test1/,/test2/p' filename

In order to exclude the lines containing test1 and test2, say:

为了排除包含test1和test2的行,例如:

sed -n '/test1/,/test2/{/test1/b;/test2/b;p}' filename

#3


7  

If you can only use grep:

如果您只能使用grep:

grep -A100000 test1 file.txt | grep -B100000 test2 > new.txt

grep -A and then a number gets the lines after the matching string, and grep -B gets the lines before the matching string. The number, 100000 in this case, has to be large enough to include all lines before and after.

grep -A,然后一个数字获取匹配字符串后面的行,grep -B获取匹配字符串前面的行。在这种情况下,100000这个数字必须足够大,足以包括前后的所有行。

If you don't want to include test1 and test2, then you can remove them afterwards by grep -v, which prints everything except the matching line(s):

如果您不想包含test1和test2,那么您可以在之后通过grep -v删除它们,它将打印除匹配行之外的所有内容:

egrep -v "test1|test2" new.txt > newer.txt

or everything in one line:

或者一切都在一行:

grep -A100000 test1 file.txt | grep -B100000 test2 | egrep -v "test1|test2" > new.txt 

#4


5  

Yep, normal grep won't do this. But grep with -P parameter will do this job.

是的,正常的grep不会这么做。但是带-P参数的grep将完成这项工作。

$ grep -ozP '(?s)test1\n\K.*?(?=\ntest2)' file
abc
cvb
bnm

\K discards the previously matched characters from printing at the final and the positive lookahead (?=\ntest2) asserts that the match must be followed by a \n newline character and then test2 string.

\K丢弃了在期末打印时之前匹配的字符,而积极的lookahead (?=\ntest2)断言匹配之后必须有一个\n个换行字符,然后是test2字符串。

#5


0  

The following script wraps up this process. More details in this similar * post

下面的脚本将结束这个过程。更多细节在这类似的堆栈溢出邮件。

get_text.sh

function show_help()
{
  HELP=$(doMain $0 HELP)
  echo "$HELP"
  exit;
}

function doMain()
{
  if [ "$1" == "help" ]
  then
    show_help
  fi
  if [ -z "$1" ]
  then
    show_help
  fi
  if [ -z "$2" ]
  then
    show_help
  fi

  FILENAME=$1
  if [ ! -f $FILENAME ]; then
      echo "File not found: $FILENAME"
      exit;
  fi

  if [ -z "$3" ]
  then
    START_TAG=$2_START
    END_TAG=$2_END
  else
    START_TAG=$2
    END_TAG=$3
  fi

  CMD="cat $FILENAME | awk '/$START_TAG/{f=1;next} /$END_TAG/{f=0} f'"
  eval $CMD
}

function help_txt()
{
HELP_START
  get_text.sh: extracts lines in a file between two tags

  usage: FILENAME {TAG_PREFIX|START_TAG} {END_TAG}

  examples:
    get_text.sh 1.txt AA     => extracts lines in file 1.txt between AA_START and AA_END
    get_text.sh 1.txt AA BB  => extracts lines in file 1.txt between AA and BB
HELP_END
}

doMain $*

#6


0  

You can do something like this too. Lets say you this file test.txt with content:

你也可以这样做。假设您进行了这个文件测试。txt和内容:

a43
test1
abc
cvb
bnm
test2
kfo

You can do

你可以做

cat test.txt | grep -A10 test1 | grep -B10 test2

猫测试。txt | grep -A10 test1 | grep -B10 test2

where -A<n> is to get you n lines after your match in the file and -B<n> is to give you n lines before the match. You just have to make sure that n > number of expected lines between test1 and test2. Or you can give it large enough to reach EOF.

其中-A 在文件中匹配后得到n行,-B 在匹配前得到n行。您只需确保test1和test2之间的预期行数为n >。或者你也可以给它足够大的空间。

Result:

结果:

test1
abc
cvb
bnm
test2

#7


0  

The answer by PratPor above:

以上PratPor的回答:

cat test.txt | grep -A10 test1 | grep -B10 test2

is cool.. but if you don't know the file length:

很酷. .但如果你不知道文件的长度:

cat test.txt | grep -A1000 test1 | grep -B1000 test2

Not deterministic, but not too bad. Anyone have better (more deterministic)?

不确定性,但不太坏。谁有更好的(更确定性的)?

#8


-3  

awk '/test1/,/test2/' filename.txt > outputFile.txt