假设您有一个txt文件,同时查看文件的前10行和后10行的命令是什么?
例如,如果文件长200行,则可以一次性查看1-10行和190-200行。
假设您有一个txt文件,同时查看文件的前10行和后10行的命令是什么?
例如,如果文件长200行,则可以一次性查看1-10行和190-200行。
Answers:
您可以简单地:
(head; tail) < file.txt
如果出于某种原因需要使用管道,则如下所示:
cat file.txt | (head; tail)
注意:如果file.txt中的行数小于默认的head首行+ tail的默认行,则将打印重复的行。
head
已经占用了文件的前10行。(将head < file.txt; tail < file.txt
其与少于20行的文件进行比较)。请记住,这只是一个非常小的要点。(但仍为+1。)
head
仅显示输入的前10行,但不能保证它不会消耗更多的行来查找第10行的结尾,而剩下的输入则更少less
。
seq 100 | (head; tail)
仅给我前10个数字。只有在更大的输入大小(如seq 2000
)上,尾巴才会获得一些输入。
对于纯流(例如,命令的输出),可以使用“ tee”来分叉该流,并将一个流发送到头,将一个流发送到尾。这需要使用bash(+ / dev / fd / N)的'>(list)'功能:
( COMMAND | tee /dev/fd/3 | head ) 3> >( tail )
或使用/ dev / fd / N(或/ dev / stderr)以及具有复杂重定向的子shell:
( ( seq 1 100 | tee /dev/fd/2 | head 1>&3 ) 2>&1 | tail ) 3>&1
( ( seq 1 100 | tee /dev/stderr | head 1>&3 ) 2>&1 | tail ) 3>&1
(这些都不能在csh或tcsh中工作。)
对于更好控制的东西,可以使用以下perl命令:
COMMAND | perl -e 'my $size = 10; my @buf = (); while (<>) { print if $. <= $size; push(@buf, $_); if ( @buf > $size ) { shift(@buf); } } print "------\n"; print @buf;'
COMMAND | { tee >(head >&2) | tail; } |& other_commands
cat >/dev/null
修复它:COMMAND | { tee >(head >&2; cat >/dev/null) | tail; } |& other_commands
head
与tail
命令之间没有保证的顺序:\ ...
head -10 file.txt; tail -10 file.txt
除此之外,您需要编写自己的程序/脚本。
cat
和/ head
或tail
管道传输,很高兴知道我可以单独使用它们!
{ head file; tail file; } | prog
在花括号内有间距,并且必须在结尾加上分号)
cat file | { tee >(head >&3; cat >/dev/null) | tail; } 3>&1
这样,您可以在一个管道中以不同方式处理第一行和其余行,这对于处理CSV数据非常有用:
{ echo N; seq 3;} | { tee >(head -n1 | sed 's/$/*2/' >&3; cat >/dev/null) | tail -n+2 | awk '{print $1*2}'; } 3>&1
N * 2 2 4 6
这里的问题是,面向流的程序无法事先知道文件的长度(因为如果是真正的流,可能不会有一个文件的长度)。
像tail
缓冲最后看到的n行之类的工具,然后等待流的结尾,然后打印。
如果要在单个命令中执行此操作(并使它具有任何偏移量,并且如果行重叠则不要重复行),则必须模仿我提到的这种行为。
试试这个awk:
awk -v offset=10 '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' yourfile
a.out | awk -v ...
最终花了很多时间才能解决此问题,该解决方案似乎是涵盖所有用例的唯一解决方案(到目前为止):
command | tee full.log | stdbuf -i0 -o0 -e0 awk -v offset=${MAX_LINES:-200} \
'{
if (NR <= offset) print;
else {
a[NR] = $0;
delete a[NR-offset];
printf "." > "/dev/stderr"
}
}
END {
print "" > "/dev/stderr";
for(i=NR-offset+1 > offset ? NR-offset+1: offset+1 ;i<=NR;i++)
{ print a[i]}
}'
功能列表:
我一直在寻找这种解决方案一段时间。我自己用sed进行了尝试,但是事先不知道文件/流的长度的问题是无法克服的。在上面所有可用的选项中,我喜欢Camille Goudeseune的awk解决方案。他确实注意到,他的解决方案在输出中留出了多余的空白行,并带有足够小的数据集。在这里,我对他的解决方案进行了修改,删除了多余的行。
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { a_count=0; for (i in a) {a_count++}; for (i=NR-a_count+1; i<=NR; i++) print a[i] }' ; }
file.ext的前10行,然后是后10行:
cat file.ext | head -10 && cat file.ext | tail -10
文件的最后10行,然后是前10行:
cat file.ext | tail -10 && cat file.ext | head -10
然后,您也可以将输出通过管道传递到其他位置:
(cat file.ext | head -10 && cat file.ext | tail -10 ) | your_program
tail
and head
或一个函数(通过对其别名)。
我编写了一个简单的python应用程序来执行此操作:https : //gist.github.com/garyvdm/9970522
它处理管道(流)以及文件。
要处理管道(流)以及文件,请将其添加到.bashrc或.profile文件中:
headtail() { awk -v offset="$1" '{ if (NR <= offset) print; else { a[NR] = $0; delete a[NR-offset] } } END { for (i=NR-offset+1; i<=NR; i++) print a[i] }' ; }
那你不仅可以
headtail 10 < file.txt
但是也
a.out | headtail 10
(与普通输入不同,当输入的长度超过10时,此行仍会附加虚假的空白行a.out | (head; tail)
。谢谢以前的答复者。)
注意:headtail 10
,不是headtail -10
。
要打印文件的前10行和后10行,您可以尝试以下操作:
cat <(head -n10 file.txt) <(tail -n10 file.txt) | less
sed -n "1,10p; $(( $(wc -l ${aFile} | grep -oE "^[[:digit:]]+")-9 )),\$p" "${aFile}"
注意:aFile变量包含文件的完整路径。
我要说的是,根据文件的大小,可能不希望主动读取其内容。在这种情况下,我认为一些简单的shell脚本就足够了。
这是我最近对大量正在分析的CSV大文件进行处理的方式:
$ for file in *.csv; do echo "### ${file}" && head ${file} && echo ... && tail ${file} && echo; done
这会打印出每个文件的前10行和后10行,同时还会打印出文件名和前后的省略号。
对于单个大文件,您可以简单地运行以下命令以获得相同的效果:
$ head somefile.csv && echo ... && tail somefile.csv