sed编辑多行
当涉及到多行编辑时,Sed编辑对我来说总是一个新的挑战。在这种情况下,我有以下模式:sed编辑多行,sed,pattern-matching,sh,multiline,Sed,Pattern Matching,Sh,Multiline,当涉及到多行编辑时,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 ,4
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是强制性的。不太清楚您如何识别要注释掉的块,因此我将使用以
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 -i -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w /dev/stdout' -e 'x; s/\(^\|\n\)/&#/g }' filename
附录:为保持线条结构完整,请使用
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/\(^\|\n\)/&#/g }' filename
除了删除换行符,并且在每一个换行符之后插入注释符号(并且在开始处插入一次)之外,其工作方式基本相同
附录2:将记录块放在一行上:
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g }' filename
这只是删除了s/^/#/
位的第一个脚本
附录3:隔离记录块,同时将它们放在一行上
sed -n '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; p }' filename
sed -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w saved_records.txt' -e 'x; s/\(^\|\n\)/&#/g }' foo.txt
-n
标志会抑制正常的默认打印操作,而p
命令会将其替换为需要打印的行
要将这些记录写入文件,同时在正常输出中注释它们
sed -n '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; p }' filename
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,可以修改如下:
/^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 -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
命令的目标。不太清楚如何识别要注释掉的块,因此我将使用以RECORD
开头的行中的块,只要有,就进行处理末尾的反斜杠(如果您的要求不同,则需要相应地修改所使用的模式)
sed '/^RECORD.*\\$/,/[^\\]$/ s/^/#/
s/^RECORD.*/#&/' YourFile
为此,你可以使用
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 -i -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w /dev/stdout' -e 'x; s/\(^\|\n\)/&#/g }' filename
附录:为保持线条结构完整,请使用
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/\(^\|\n\)/&#/g }' filename
除了删除换行符,并且在每一个换行符之后插入注释符号(并且在开始处插入一次)之外,其工作方式基本相同
附录2:将记录块放在一行上:
sed '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g }' filename
这只是删除了s/^/#/
位的第一个脚本
附录3:隔离记录块,同时将它们放在一行上
sed -n '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; p }' filename
sed -e '/^RECORD/ { :a /\\$/ { N; ba }; h; s/[[:space:]]*\\\n[[:space:]]*/ /g; w saved_records.txt' -e 'x; s/\(^\|\n\)/&#/g }' foo.txt
-n
标志会抑制正常的默认打印操作,而p
命令会将其替换为需要打印的行
要将这些记录写入文件,同时在正常输出中注释它们
sed -n '/^RECORD/ { :a /\\$/ { N; ba }; s/[[:space:]]*\\\n[[:space:]]*/ /g; p }' filename
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,可以修改如下:
/^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 -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
命令的目标
sed '/^RECORD.*\\$/,/[^\\]$/ s/^/#/
s/^RECORD.*/#&/' YourFile
在@Wintermute的几句评论和OP的更多信息之后
假设:
- 开始时带有
是修改下一行的触发器记录的行
- 结构相同(没有带
的行,有\
行直接跟在后面,或者是空行)记录
- 以
记录开始,以
结束的行块\
- 在每行前面添加
#
- 在每行前面添加
- 获取行(因此,在对前面的块进行最终修改后,只在末尾留下不带
的记录行或不带记录的行),如果以\
记录开始,则在开头添加一个
\
- 开始时带有
是修改下一行的触发器记录的行
- 结构相同(没有带
的行,有\
行直接跟在后面,或者是空行)记录
- 以
记录开始,以
结束的行块\
- 在每行前面添加
#
- 在每行前面添加
- 获取行(因此,在对前面的块进行最终修改后,只在末尾留下不带
的记录行或不带记录的行),如果以\
记录开始,则在开头添加一个
\