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

当涉及到多行编辑时,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是强制性的。

不太清楚您如何识别要注释掉的块,因此我将使用以
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的更多信息之后

假设:

  • 开始时带有
    记录的行
    是修改下一行的触发器
  • 结构相同(没有带
    \
    的行,有
    记录
    行直接跟在后面,或者是空行)
说明:

  • 记录开始,以
    \
    结束的行块
    • 在每行前面添加
      #
  • 获取行(因此,在对前面的块进行最终修改后,只在末尾留下不带
    \
    的记录行或不带记录的行),如果以
    记录开始,则在开头添加一个
    \
在@Wintermute的几句评论和OP的更多信息之后

假设:

  • 开始时带有
    记录的行
    是修改下一行的触发器
  • 结构相同(没有带
    \
    的行,有
    记录
    行直接跟在后面,或者是空行)
说明:

  • 记录开始,以
    \
    结束的行块
    • 在每行前面添加
      #
  • 获取行(因此,在对前面的块进行最终修改后,只在末尾留下不带
    \
    的记录行或不带记录的行),如果以
    记录开始,则在开头添加一个
    \
我不这么认为