Bash 在两个字符串之间打印文件内容
Bash print file contents between two strings
a
b
s
start
text
more text
end
even more text
end
我想打印 start
和 start
之后的第一个 end
之间的内容(start
总是唯一的)。我还想打印在哪些行之间打印了文本,在本例中是第 4 行和第 7 行之间。
我尝试使用 grep
和 cat
,但我做不了什么。
我试过了:
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
,然后按范围打印文本,然后尝试在 awk
的 start
变量中提及您的 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"
,结果不符合预期;虽然可以添加更多代码来解决这种情况,但我将暂时跳过这种情况。
a
b
s
start
text
more text
end
even more text
end
我想打印 start
和 start
之后的第一个 end
之间的内容(start
总是唯一的)。我还想打印在哪些行之间打印了文本,在本例中是第 4 行和第 7 行之间。
我尝试使用 grep
和 cat
,但我做不了什么。
我试过了:
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
,然后按范围打印文本,然后尝试在 awk
的 start
变量中提及您的 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"
,结果不符合预期;虽然可以添加更多代码来解决这种情况,但我将暂时跳过这种情况。