我有一个文本文件,其中包含许多 60 个字符长的行,我使用“/”命令进行搜索以突出显示匹配项。我想用突出显示的文本直观地检查这个长文件,但采用多窗格布局,而不是仅在终端窗口的前 60 个字符中显示文本。例如:
less file.txt
/CG <enter> #to find occurrences of token 'CG'
而不是像这样有 60 个字符的行:
xxxxxxxxxx
xxxxCGxxxx
xxxxxxxxxx
xxxxxxCGxx
xxxCGxxxxx
[...]
我想要有这样的东西(这里有 4 个垂直窗格):
xxxxxxCGxx|xxCGxxxxxx|xxCGxxxxxx|xxxxxxxxxx
xxxxxxxxxx|xxxxxxxxxx|xxxxxxxCGx|xxxxCGxxxx
xxxxCGxxxx|xxxxCGxxxx|xxxxxxxxxx|xxxxxxxxxx
xxxxxxxxxx|xxxxxxxxxx|xxxxxCGxxx|xxxCGxxCGx
xxCGxxxxxx|xxxxxxCGxx|xxxxxxxxxx|xxxxxxxxxx
[...]
这样,每次我点击“Page Down”时,我都会向下滚动比一个窗格多 4 倍的文本。
答案1
这很简单,只需要一点技巧。以前当我需要类似的东西时,我就是这样做的(但为了正确执行,您需要先找出文件的总行数,并在行结束后停止捕获行,否则您需要按 ctrl-c 来结束循环,如果您没有 $tot_lines % $col_num==0,您将丢失最后一行)
perl -lne '$|=1; $c1= $_; $c2=scalar <>; $c3=scalar <>; \
chomp($c1, $c2, $c3); \
print join("|", $c1, $c2, $c3); \
' \
long_text_60_chars.txt \
| less
这是简单的答案,输入线按行分布。
[注意] 如果您想将其传递给,则需要取消缓冲打印less
(因为当输入<>
行数少于所需行数时需要等待<>
)
您想让程序复杂化,并希望行按列分布,但您需要知道分页器行的大小和文件的总行数。对于 50 行分页器:
perl -lne 'BEGIN{$|=1; $max = 1301; $cl = 50; $pl = $cl*3; $pleft=$max % $pl; $cleft=$max % $cl; $pmax=$max - $pleft; $cmax=$max - $cleft; print "cleft $cleft, pleft $pleft, pmax $pmax, cmax $cmax"}; if ($.<=$pmax){ @c1= ($_,map{$x=<>;chomp $x;$x} 2..$cl); @c2=map{$x=<>;chomp $x;$x} 1..$cl; @c3=map{$x=<>;chomp $x;$x} 1..$cl; foreach my $idx (0..($cl-1)){ print join("|", $c1[$idx], $c2[$idx], $c3[$idx]) }; print (q{=} x (3*60).qq{\n}); print "line $., pmax $pmax"; } else { print }' long_text_60_chars_with_num_line.txt | less
我放了很多调试信息,以便您可以根据自己的需要进行调整。
这是一个人性化的版本(但复制粘贴可能不起作用)
perl -lne 'BEGIN{$|=1; \
# max num lines (from wc -l) \
$max=1301; \
#lines per col \
$cl=50; \
# lines per pager \
$pl=$cl*3; \
# remainder lines for pager \
$pleft=$max % $pl; \
# remainder lines for col \
$cleft=$max % $cl; \
# max line for last full 3col page \
$pmax=$max - $pleft; \
# max line for last full column \
$cmax=$max - $cleft; \
# print info \
print "cleft $cleft, pleft $pleft, pmax $pmax, cmax $cmax"}; \
# END BEGIN \
# START -n while LOOP \
if ($.<=$pmax){ \
# full 3col pages \
@c1= ($_,map{$x=<>;chomp $x;$x} 2..$cl); \
@c2=map{$x=<>;chomp $x;$x} 1..$cl; \
@c3=map{$x=<>;chomp $x;$x} 1..$cl; \
foreach my $idx (0..($cl-1)){ \
print join("|", $c1[$idx], $c2[$idx], $c3[$idx]) \
}; \
print (q{=} x (3*60).qq{\n}); \
print "line $., pmax $pmax"; \
} else { \
# lazy approach: everyting else one column \
print \
}' \
long_text_60_chars_with_num_line.txt \
| less
答案2
将文件剪切成屏幕大小的行块,然后paste
用管道分隔符将其重新组合在一起:
#!/bin/bash
working=/tmp/split.$$
pastetmp=/tmp/pasted.$$
screen_height=25
panes=4
rm -rf "$working" "$pastetmp"
mkdir -p "$working"
cd "$working"
split -l "$screen_height" "$1"
four=()
for file in * ; do
four=("${four[@]}" "$file")
if [ ${#four[@]} = "$panes" ] ; then
paste -d'|' "${four[@]}" >> "$pastetmp"
four=()
fi
done
[ ${#four[@]} -gt 0 ] && paste -d'|' "${four[@]}" >> "$pastetmp"
less "$pastetmp"
调用方式如下:
./script file.txt
注意:未经测试,但您明白了。