Æva*_*son 7 linux shell perl tail
我试图找到一个简洁的shell单行程序,它会在文件中提供所有行,直到某种模式.
用例是将所有行转储到日志文件中,直到我发现一些标记表明服务器已重新启动.
这是一种愚蠢的shell专用方式:
tail_file_to_pattern() {
pattern=$1
file=$2
tail -n$((1 + $(wc -l $file | cut -d' ' -f1) - $(grep -E -n "$pattern" $file | tail -n 1 | cut -d ':' -f1))) $file
}
Run Code Online (Sandbox Code Playgroud)
在stdin上获取文件的稍微更可靠的Perl方式:
perl -we '
push @lines => $_ while <STDIN>;
my $pattern = $ARGV[0];
END {
my $last_match = 0;
for (my $i = @lines; $i--;) {
$last_match = $i and last if $lines[$i] =~ /$pattern/;
}
print @lines[$last_match..$#lines];
}
'
Run Code Online (Sandbox Code Playgroud)
当然,你可以更有效地打开文件,寻找到最后并回头找到匹配的行.
在第一次出现时很容易打印所有内容,例如:
sed -n '/PATTERN/,$p'
Run Code Online (Sandbox Code Playgroud)
但是我还没有想出一种方法来打印最后一次出现的所有东西 .
这是一个仅限sed的解决方案.要从匹配的最后一行$file 开始打印每一行$pattern:
sed -e "H;/${pattern}/h" -e '$g;$!d' $file
Run Code Online (Sandbox Code Playgroud)
请注意,与您的示例一样,只有在文件包含模式时才能正常工作.否则,它输出整个文件.
以下是括号中的sed命令:它的功能细分:
另请注意,对于非常大的文件,它可能会变慢,因为任何单通道解决方案都需要在内存中保留一堆行.
我建议简化你的 shell 脚本:
tail -n +$(grep -En "$pattern" "$file" | tail -1 | cut -d: -f1) "$file"
Run Code Online (Sandbox Code Playgroud)
它更加简洁,因为它:
+选项从给定行打印到末尾,而不必计算从那里到末尾的距离。它通过引用 $file 修复了一个错误(因此它将适用于名称包含空格的文件)。