Bash 在两个字符串之间打印文件内容

Bash print file contents between two strings

a
b
s
start
text
more text
end
even more text
end

我想打印 startstart 之后的第一个 end 之间的内容(start 总是唯一的)。我还想打印在哪些行之间打印了文本,在本例中是第 4 行和第 7 行之间。

我尝试使用 grepcat,但我做不了什么。

我试过了:

var=$(cat $path)
echo "$var" | grep -o -P '(?<=start).*(?=end)'

但是它没有打印任何东西,没有 grep,它打印了整个文件。

此示例中的输出应为:

The content is between lines 4 and 7.

start
text
more text
end

将 shell 变量传递给 awk,然后按范围打印文本,然后尝试在 awkstart 变量中提及您的 shell 变量,并且那我们应该很好。 (也可以将 [=15=] ~ start 更改为 [=16=] ~ "^"start"$",以防您想在行中查找起始值的完全匹配项。)

awk -v start="$your_shell_start_var" '
[=10=] ~ start,[=10=] ~ /^end$/{
  print
  if([=10=] ~ start){ startLine=FNR }
  if([=10=]~/^end$/){ 
     print "The content is between lines " startLine " and " FNR
     exit
  }
}' Input_file

OP样本的样本输出:

start
text
more text
end
The content is between lines 4 and 7

简单的解释: 在此语句之间按范围打印行 start 直到 end 检查条件 if行有结束字符串然后从 Input_file 出来,我们不需要阅读完整的 Input_file 因为 OP 只需要打印第一组行。

示例数据:

$ cat -n strings.dat
 1  a
 2  b
 3  s
 4  start
 5  text
 6  more text
 7  end of more text
 8  end
 9  even more text
10  end

一个 awk 使用范围(类似于 RavinderSingh13 的 post)的解决方案,在末尾打印出 OP 的文本消息:

startstring="start"                            # define start of search block

awk -v ss="${startstring}" '                   # pass start of search block in as awk variable "ss"

# search for a range of lines between "ss" and "end":

[=11=]==ss,/^end$/ { if ([=11=]==ss && x==0 ) x=FNR    # if this is the first line of the range make note of the line number
                 print                         # print the current line of the range
                 if ([=11=]=="end")                # if this is the last line of the range then print our textual message re: start/finish line numbers
                    printf "\nThe content is between lines %d and %d.\n",x,FNR
               }
' strings.dat

注意[=17=]==ss/^end$/测试假定数据文件中没有leading/trailing白色space,否则这些测试将失败并且不会有范围匹配。

使用 startstring="start" 这会生成:

start
text
more text
end of more text
end

The content is between lines 4 and 8.

使用 startstring="more text" 这会生成:

more text
end of more text
end

The content is between lines 6 and 8.

使用 startstring="even more text" 这会生成:

even more text
end

The content is between lines 9 and 10.

使用 startstring="water" 这会生成:

--no output--

注意:如果 OP 使用 startstring="end",结果不符合预期;虽然可以添加更多代码来解决这种情况,但我将暂时跳过这种情况。