有了sed
你可以做:
sed '24q;1,5d;12,18d' <infile >outfile
...可能有一个更有效的解决方案head
。Don已经演示了如何很好地工作,但是我也一直在研究它。您可能需要处理以下特定情况:
for n in 5 6 7 6
do head -n"$n" >&"$((1+n%2))"
done <infile >outfile 2>/dev/null
...这将调用head
4次写入outfile
或,/dev/null
具体取决于该迭代的值$n
是偶数还是奇数。
对于更一般的情况,我将我已经拥有的其他一些东西拼凑起来:
somehead()(
### call it like:
### somehead -[repeat] [-][numlines]* <infile >outfile
set -e -- "${1#-}" "$@" #-e for arg validation
r=; cd -- "${TMP:-/tmp}" #go to tmp
dd bs=4096 of="$$$$" <&4 2>&3 & #dd <in >tmpfile &bg
until [ -s "$$$$" ]; do :; done #wait while tmpfile empty
exec <"$$$$" 4<&-; rm "$$$$" #<tmpfile; rm tmpfile
[ "$3${1}0" -ne "$3${2#?}0" ] || #validate args - chk $1
shift "$(((r=-${1:--1})||1))"; shift #shift 1||2
while [ "$(((r+=(_n=1))-1))" -ne 0 ] && #while ! $rptmax &&
IFS= read -r l && # ! EOF &&
printf "%.$(($1>0?${#l}+1:0))s" "$l # ? printf do
"; do for n do [ "${n#-}" -gt 0 ] || exit #args all -[nums>0]
head "-n$((${n#-}-_n))" >&"$((n>(_n=0)?1:3))" #head -n?$1 >?[+-]
done; done #done and done
) 4<&0 3>/dev/null #4<for dd 3>for head
这可以做你的事情,例如:
seq 100 | somehead -1 -5 6 -7 6
...打印...
6
7
8
9
10
11
19
20
21
22
23
24
它期望其第一个arg是一个重复计数,前缀为a -
,否则,为a -
。如果提供了计数,它将重复以下args中指定的线型并重复指定次数,并在这样做后立即停止。
对于后面的每个arg,它将解释一个负整数以指示应写入/dev/null
的行数,并解释一个正整数以指示应写入的行数stdout
。
所以在上面的例子中,它打印的前5行/dev/null
,接下来的6行stdout
,接下来的7行/dev/null
和接下来的6行stdout
。到达其最后一个args并完全循环进行-1
重复计数后,它退出。如果是第一个参数,-2
它将再重复一次该过程,或者-
尽可能重复一次。
对于每个arg循环,while
循环都要处理一次。在每个循环的顶部,从第一行开始stdin
将其读入shell变量$l
。这是必要的,因为while head </dev/null; do :; done
它将无限期地重复- head
确实会在到达文件末尾时在返回中进行指示。因此,仅当第二个参数为正整数时,针对EOF的检查才专用于该操作,read
并且printf
将向该操作$l
加上一个换行符stdout
。
该read
检查使该循环有些复杂,因为在调用另一个循环之后立即进行了循环- for
循环遍历args,2-$#
如$n
其父while
循环的每次迭代中所示。这意味着对于每次迭代,第一个arg必须从命令行上指定的值减1,但是所有其他arg都应保留其原始值,因此$_n
将从每个arg 中减去标记var 的值,但仅保留一个第一个arg的值大于0。
这构成了函数的主循环,但大部分代码位于顶部,旨在使函数甚至可以干净地缓冲管道作为输入。通过首先调用后台dd
将其复制到tmpfile上,以4k的块大小进行输出,可以实现此目的。然后,该函数设置一个保持循环-即使在一个完整的周期内也几乎永远不会完成-只是为了确保dd
在该函数随后用链接到tmpfile的文件描述符替换其stdin之前至少对该文件进行了一次写入之后立即取消链接rm
。这使函数能够可靠地处理流,而无需陷阱或进行其他清理-一旦函数释放它在fd上的声明,则tmpfile将不再存在,因为其唯一的命名文件系统链接已被删除。
head
和tail
?如果是这样,您的解决方案几乎是您可以做到的最好的方法。如果允许您使用其他程序,sed
或者awk
允许使用更好的解决方案(例如,较少的流程调用)。