这怎么可能在 shell 中使用sed或任何其他过滤器
假设我在两个变量$line1
和$line2
中有两个特定的行号,我想像这样提取这两行之间的行
cat my_file_path | command $line1 $line2
例如,如果我的文件是:
1:BBB
2:中交
3:DDDD
4:呜
如果我这样做,我的输出应该是:
cat my_file_path | command 1 3
输出
bbb
cccc
使用 sed:
$ cat my_file_path | sed -n "${line1},${line2}p"
或者,甚至更好(cat
在某种程度上是多余的):
$ sed -n "${line1},${line2}p" my_file_path
您可以使用带有尾巴和头部的管道
tail -n +$line1 | head -n $((line2-line1))
无需测试:
awk -v s="$line1" -v e="$line2" 'NR>s&&NR<e' file
您可以使用>= or <=
控制"包容性/排他性"
如果要确保 shell var 中的前导/尾随空格安全:
awk -v s="$line1" -v e="$line2" 'NR>1*s&&NR<1*e' file
这是我在 Centos 上使用的,此示例从myFile打印 100 到 200 之间的行.log
awk 'NR >= 100 && NR <= 200' myFile.log
100 之前的其他示例行
awk 'NR <= 100' fileName.log
请注意,您也可以使用>,<比较器。>
这个答案使用 NR 变量(又名记录号)作为行号,用于更复杂的场景 您可以查看 AWK 内置变量: https://www.thegeekstuff.com/2010/01/8-powerful-awk-built-in-variables-fs-ofs-rs-ors-nr-nf-filename-fnr/
希望它有帮助
使用sed打印 100 和 200 之间的行(专门!):
sed '1,100d;200,$d' file
优化:遇到范围结束时退出。
sed -n '1,100b;200q;p' file
优化使用b
命令:
b
– 无条件分支(即:始终跳转到标签,跳过 或重复其他命令,而不重新启动新周期)[...]如果省略标签,分支命令将重新启动循环。
GNU sed 手册:分支和流量控制
测试优化是否有效。我们将使用超精细命令行基准测试工具。
seq 1 1000000 >file # A file with 1,000,000 lines
hyperfine --warmup 5
--command-name 'unoptimized' 'sed '''1,100d;200,$d''' file'
--command-name 'optimized' 'sed -n '''1,100b;200q;p''' file'
结果:
'optimized' ran
80.76 ± 45.66 times faster than 'unoptimized'
按理说,行越靠近文件的开头,优化就越有利。
我们也应该测试相反的情况:感兴趣的行位于文件的末尾:
hyperfine --warmup 5
--command-name 'unoptimized' 'sed '''1,900900d;1000000,$d''' file'
--command-name 'optimized' 'sed -n '''1,900900b;1000000q;p''' file'
结果:
'unoptimized' ran
1.03 ± 0.05 times faster than 'optimized'
您会看到优化的形式也为这种情况带来了好处,尽管非常小并且在误差范围内。
使用 awk:
印刷行 100 到 200 专用:
awk 'NR==200{p=0};p;NR==100{p=1}' file
优化:打印出所需范围的最后一行后退出:
awk 'NR==200{exit};p;NR==100{p=1}' file
测试优化是否有效。我们将使用超精细命令行基准测试工具。
seq 1 1000000 >file # Create a file with 1,000,000 lines
hyperfine --warmup 5
--command-name 'unoptimized' 'awk '''NR==200{p=0};p;NR==100{p=1}''' file'
--command-name 'optimized' 'awk '''NR==200{exit};p;NR==100{p=1}''' file'
结果:
'optimized' ran
80.87 ± 33.69 times faster than 'unoptimized'
上面的基准测试了感兴趣线靠近文件开头的情况。我们还应该对相反的情况进行基准测试,有趣的台词接近尾声:
hyperfine --warmup 5
--command-name 'unoptimized' 'awk '''NR==900100{p=0};p;NR==900000{p=1}''' file'
--command-name 'optimized' 'awk '''NR==900100{exit};p;NR==900000{p=1}''' file'
结果:
'optimized' ran
1.11 ± 0.03 times faster than 'unoptimized'
优化仍然是一个好处,但影响不大。
将 awk 与 sed 进行比较。我们将优化的awk与我基于sed的答案的优化版本进行比较。
这次我选择位于 1,000,000 行文件中间的行:
hyperfine --warmup 5
--command-name 'awk version' 'awk '''NR==500100{exit};p;NR==500000{p=1}''' file'
--command-name 'sed version' 'sed -n '''1,500000b;500100q;p''' file'
结果:
'sed version' ran
4.08 ± 0.09 times faster than 'awk version'
sed 版本明显更快。它也更短。我也会给 sed 版本在可读性方面带来优势,但这是主观的。
不是确切的答案,但对于任何进行一些手动日志文件调查并希望在不费吹灰之力和行计算的情况下提取大量行的人都可能很有用,尤其是在涉及tail -f
时。尝试less the-big-log-file.log
:
- 打开文件,转到起始位置(例如,使用
/2021-11-21 19:00
搜索)。 - 使用命令标记当前位置
mM
- 然后转到结束位置,例如
/2021-11-23 23:00
搜索。 - 使用以下命令提取标记点和结束位置之间的线以分隔文件:
|Mtee log-excerpt.txt
。
您将在当前目录中找到日志摘录.txt,其中包含两个搜索结果位置之间的所有行。