对于多行编辑,sed编辑对我来说总是一个新的挑战。在这种情况下,我有以下模式:
RECORD 4,4 ,5,48 ,7,310 ,10,214608 ,12,199.2 ,13,-19.2 ,15,-83 ,17,35 \
,18,0.8 ,21,35 ,22,31.7 ,23,150 ,24,0.8 ,25,150 ,26,0.8 ,28,25 ,29,6 \
,30,1200 ,31,1 ,32,0.2 ,33,15 ,36,0.4 ,37,1 ,39,1.1 ,41,4 ,80,2 \
,82,1000 ,84,1 ,85,1
我想转换成:
#RECORD 4,4 ,5,48 ,7,310 ,10,214608 ,12,199.2 ,13,-19.2 ,15,-83 ,17,35 \
# ,18,0.8 ,21,35 ,22,31.7 ,23,150 ,24,0.8 ,25,150 ,26,0.8 ,28,25 ,29,6\
# ,30,1200 ,31,1 ,32,0.2 ,33,15 ,36,0.4 ,37,1 ,39,1.1 ,41,4 ,80,2 \
# ,82,1000 ,84,1 ,85,1
除此之外,我想保留这4行的全部(可能多于或少于4行(在输入中出现不可预测)到一条(长)行而没有反斜杠或换行。
一个人可以说两个任务。
sed是强制性的。
答案 0 :(得分:3)
你不清楚如何识别要注释掉的块,所以我会使用以RECORD
开头的行中的块并处理只要有反斜杠的块结束(如果您的要求不同,使用的模式将需要相应修改)。
为此,您可以使用
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; s/^/#/ }' filename
其工作原理如下:
/^RECORD/ { # if you find a line that starts with
# RECORD:
:a # jump label for looping
/\\$/ { # while there's a backslash at the end
# of the pattern space
N # fetch the next line
ba # loop.
}
# After you got the whole block:
s/[[:space:]]*\\\n[[:space:]]*/ /g # remove backslashes, newlines, spaces
# at the end, beginning of lines
s/^/#/ # and put a comment sign at the
# beginning.
}
附录:为了保持线条结构的完整性,请使用
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/\(^\|\n\)/&#/g }' filename
这种方法的工作原理大致相同,只是删除了换行符,并在每个换行符后插入注释符号(并在开头一次)。
附录2:只需将RECORD块放在一行:
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g }' filename
这只是删除s/^/#/
位的第一个脚本。
附录3:要在将RECORD块同时放入一行时隔离它们,
sed -n '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; p }' filename
-n
标志禁止正常的默认打印操作,p
命令替换我们要打印的那些行。
将这些记录写入文件,同时在正常输出中将它们注释掉,
sed -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w saved_records.txt' -e 'x; s/\(^\|\n\)/&#/g }' foo.txt
这里真的有新东西。简短注释:
#!/bin/sed -f
/^RECORD/ {
:a
/\\$/ {
N
ba
}
# after assembling the lines
h # copy them to the hold buffer
s/[[:space:]]*\\\n[[:space:]]*/ /g # put everything on a line
w saved_records.txt # write that to saved_records.txt
x # swap the original lines back
s/\(^\|\n\)/&#/g # and insert comment signs
}
直接在命令行中指定此代码时,必须将其拆分为多个-e
选项,因为w
命令未被;
终止。
将代码放入自己的文件(例如foo.sed
)并运行sed -f foo.sed filename
时,不会出现此问题。或者,对于高级版,将#!/bin/sed -f
shebang放在文件的顶部,chmod +x
然后调用./foo.sed filename
。
最后,要就地编辑输入文件并将记录打印到stdout,可以修改如下:
sed -i -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w /dev/stdout' -e 'x; s/\(^\|\n\)/&#/g }' filename
这里的新内容是-i
标志,用于现场编辑文件,并/dev/stdout
作为w
命令的目标。
答案 1 :(得分:2)
sed '/^RECORD.*\\$/,/[^\\]$/ s/^/#/
s/^RECORD.*/#&/' YourFile
经过几次关于@Wintermute的评论以及来自OP的更多信息
假设:
RECORD
对齐的行是修改下一行的触发器\
行,RECORD
行直接跟随或空行说明:
RECORD
开头并以\
结尾的行块
#
\
的RECORD行而没有记录)并且如果以{{1开头,则在开头添加#
}}