是否可以在sed地址中进行简单的算术运算? 从"addresses" manual section来看,答案似乎没有。但也许有一种解决方法?
例如,如何打印文件的倒数第二行?这会很酷:
sed -n '$-1 p' file
但它显然不起作用...所以我通常必须做多个sed调用,首先用于识别行,然后使用shell $((expr))
进行算术运算,然后再次调用sed。像这样:
sed -n "$(($(sed -n '$ =' file)-1)) p" file
是否有更好的"更简洁,更易读的方式来处理带有sed地址的算术?
在一个拖延的严重时刻,我决定写一个小script that quickly changes the xterm colorscheme。我们的想法是,.Xresources
文件包含开始标记和结束标记:
...
START_MARKER
...
END_MARKER
...
并且您想要删除标记之间的所有内容,而不是标记本身。再一次,这样做会很棒:
sed '/START_MARKER/+1,/END_MARKER/-1 d' file
......但你不能!
答案 0 :(得分:3)
你是对的,不能直接在sed 1 中做数学,甚至是地址。但你可以用一些技巧来做你想做的事:
倒数第二行:
$ seq 5 | sed -n -e '${ # On the last line
> g # Replace the buffer with the hold space
> p # and print it
> }
> h' # All lines, store the current line in the hold space.
4
在START
和END
之间:
$ cat test.in
1
START
2
3
END
4
$ cat test.in | sed '/^START$/,/^END$/{
> /^START$/d
> /^END$/d
> p
> }
> d'
2
3
$ cat test.in | sed -n -e '/^START$/,/^END$/!d' -e '/^START/d' -e '/^END$/d' -e p
2
3
我正在使用BSD(mac)sed
;在GNU系统上,您可以在行之间使用;
而不是换行符。或者将其粘贴在脚本中。
1:Sed是图灵完成的,所以你可以做数学,但它充其量是笨重的:http://rosettacode.org/wiki/A%2BB#sed
是的,我知道,UUOC;这只是为了说明
答案 1 :(得分:1)
删除第二行:
sed ':r;$!{N;br};s/\n[^\n]*\(\n[^\n]*\)$/\1/' file
删除标记内的所有内容:
sed ':r;$!{N;br};s/START_MARKER.*END_MARKER/START_MARKER\nEND_MARKER/' file
远非优雅,但有点有效。
正如评论中提到的那样,sed
在线上运作。但是,您可以使用N
命令将另一行读入模式空间。这两行现在都在模式空间中,并将用\n
分隔。 sed
还具有执行流控制的手段,即标签和条件/无条件分支。 man sed
中记录了所有内容,here也是完整的参考示例。在上面的代码中,r
是一个标签; $!{..}
表示“除了最后一行以外的任何地方,请..
; N;br
读取另一行,并无条件地再次分支到r
。所以使用:r;$!{N;br}
您可以阅读所有输入进入模式空间,然后将其作为单行操作,\n
分隔输入行。
答案 2 :(得分:1)
这可能适合你(GNU sed);
sed '$!N;$s/.*\n//;P;D' file
这是有效的,应该很容易理解:
sed '/start/,/end/!d;//d' file
这些是您的问题的解决方案,但最好使用awk或perl。
答案 3 :(得分:0)
您有一些很好的sed
建议,这里有一个基于GNU awk
的建议:
awk -v RS='START_MARKER|END_MARKER' 'RT == "END_MARKER"' infile
RS='START_MARKER|END_MARKER'
将标记拆分为分隔符。RT
设置为匹配的分隔符,当匹配“END”时,将执行默认的块{print $0}
。因此,例如,如果您想要打印除最后三行之外的所有行,请将FS设置为\n
并应用适当的循环:
awk -v RS='START_MARKER|END_MARKER' -v FS='\n' 'RT == "END" { for(i=1; i<NF-3; i++) print $i }' infile
答案 4 :(得分:-1)
您可以使用简单方法显示文件的倒数第二行。
TOTAL_LENGTH=$(cat file_name | wc -l)
SECOND_LAST_LINE=`expr $TOTAL_LENGTH - 1`
head -$SECOND_LAST_LINE | tail -1
如果要删除文件中的倒数第二行:
sed -i "$SECOND_LAST_LINE"d file_name