Answers:
只需将这些行复制到保持缓冲区(然后删除它们),然后在最后一行将保持缓冲区的内容追加到模式空间:
some command | sed '1,NUMBER{ # in this range
H # append line to hold space and
1h # overwrite if it's the 1st line
d # then delete the line
}
$G' # on last line append hold buffer content
随着gnu sed
你可以写成
some command | sed '1,NUMBER{H;1h;d;};$G'
这是ol'的另一种方法ed
(它将r
的输出填充some command
到文本缓冲区中,然后在最后一个之后m
保留行):1,NUMBER
$
ed -s <<IN
r ! some command
1,NUMBERm$
,p
q
IN
请注意,如前所述,如果输出少于NUMBER
+1行,它们都将失败。一个更可靠的方法是(gnu sed
语法):
some command | sed '1,NUMBER{H;1h;$!d;${g;q;};};$G'
只要该行不是最后一行($!d
),它只会删除该范围内的行-否则它会使用保持缓冲区内容(g
)和q
uit(在打印当前模式空间之后)覆盖模式空间。
sed -e '1,NUMBER{H;1h;d;}' -e '$G'
也可移植的工作(注意,一些sed
实现不能持有超过保留空间几千字节,因此NUMBER不能过大存在)
sed -e '1,NUMBER{H;1h;d' -e'}' -e '$G'
吗?
-e
替换换行符。d;}
还不是POSIX,而是可移植的。在下一个POSIX规范中将解决此问题。参见austingroupbugs.net/view.php?id=944#c2720 –StéphaneChazelas
1,NUMBER{H;1h;d;}
不立即后有一个分号开括号。不过,这可能只是SunOS 4.1中sed
的一个错误,不过20年后,它的解决方法仍然存在我的脑海。
一种awk
方法:
cmd | awk -v n=3 '
NR <= n {head = head $0 "\n"; next}
{print}
END {printf "%s", head}'
@don_crissti的sed
方法的一个好处是,如果输出的n
行数或更少,它仍然可以工作(输出行)。
\n
ORS 替换硬编码,以便与其他记录分隔符一起使用(例如,您要使用段落等)。
我有xclip
,可以用这种方式完成:
./a_command | xclip -in && xclip -o | tail -n +3 && xclip -o | head -n 2
这是它的描述:
xclip - command line interface to X selections (clipboard)
NAME
xclip - command line interface to X selections (clipboard)
SYNOPSIS
xclip [OPTION] [FILE]...
DESCRIPTION
Reads from standard in, or from one or more files, and makes the data available as an X selection for pasting into X applications. Prints current X selection to standard out.
-i, -in
read text into X selection from standard input or files (default)
-o, -out
prints the selection to standard out (generally for piping to a file or program)
Perl方式:
perl -ne '$.<3?($f.=$_):print;}{print $f'
或者,同样的东西写得不太清楚:
perl -ne 'if($.<3){ $f.=$_ } else{ print } END{print $f}'
例如:
$ cat file
44444
55555
11111
22222
33333
$ cat file | perl -ne '$.<3?($f.=$_):print;}{print $f'
11111
22222
33333
44444
55555
-ne
:逐行读取输入文件/流,然后将给定的脚本-e
应用于每一行。$.<3
:$.
是当前行号,因此请更改3
为要移动的行数。$.<3?($f.=$_):print;
:这是条件运算符,一般格式为condition ? case1 : case2
,case1
如果condition
为true和case2
false ,它将运行。在此,如果当前行号小于3,则将当前行($_
)附加到变量中$f
;如果行号大于3,则进行打印。}{ print $f
:}{
是perl的简写END{}
。处理完所有输入行后,它将运行。此时,我们将收集所有要移动的行,并打印所有我们想单独留下的行,因此打印另存为的行$f
。perl -ne '$.<3?$f.=$_:print}{print $f
使用POSIX ex
。是的,它用于文件编辑,但是可以在管道中使用。
printf %s\\n 111 222 333 444 555 | ex -sc '1,2m$|%p|q!' /dev/stdin
它可以在管道的开头或结尾添加任意命令,并且将以相同的方式工作。更好的是,考虑到的存在/dev/stdin
,它符合POSIX。
(我不知道是否/dev/stdin
在POSIX中指定了,但是我看到它在Linux和Mac OS X中都存在。)
与使用sed
的保留空间相比,这具有可读性上的优势-您只需告诉ex
“将这些行移到末尾”即可。(其余命令的意思是“打印缓冲区”和“退出”,它们也很容易阅读。)
注意:ex
如果输入少于2行,则上面给出的命令将失败。
进一步阅读:
简短python
摘要:
#!/usr/bin/env python3
import sys
file_ = sys.argv[1]
lines = int(sys.argv[2])
with open(file_) as f:
f = f.readlines()
out = f[lines:] + f[:lines]
print(''.join(out), end='')
将文件名作为第一个参数传递,并将行数作为第二个参数传递。
例:
$ cat input.txt
44444
55555
11111
22222
33333
$ ./sw_lines.py input.txt 2
11111
22222
33333
44444
55555
$ ./sw_lines.py input.txt 4
33333
44444
55555
11111
22222
这是另一个需要GNU的选项sed
:
(x=$(gsed -u 3q);cat;printf %s\\n "$x")
-u
使GNU成为sed
无缓冲的,以便该sed
命令不占用超过3行的STDIN。该命令替换将删除空行,以便在第三,第三和第二或第三,第二和第一行为空的情况下,该命令在输出的末尾不包含空行。
您还可以执行以下操作:
tee >(sponge /dev/stdout|sed -u 3q)|sed 1,3d
如果没有sponge /dev/stdout|
该命令,则输入较长时将失败。sponge /dev/stdout
也可以用代替tac|tac
,即使例如a\ncb
在输入是换行的a\nb\nc
地方打印时,也可以用代替,即使从输入末尾删除空行也可以用代替。当输入的行数为一或两时,以上命令删除第一行。\n
(x=$(cat);printf %s\\n "$x")