Awk SED删除包含图案的新行

Awk SED删除包含图案的新行,awk,sed,Awk,Sed,我想删除所有只包含一次字符的行上的sed或awk换行符,但一旦在该行上删除了换行符,就可以在下一行上删除它 这是一个例子 line1"test 2015" line2"test 2015" line3"test 2020" line4"test 2017" 应转变为: line1"test 2015" line2"test2015" line3"test 2020" line4"test2017" 使用GNU awk: 这是最直接的方法。用作记录分隔符 NR % 2 == 0 {

我想删除所有只包含一次字符的行上的sed或awk换行符,但一旦在该行上删除了换行符,就可以在下一行上删除它

这是一个例子

line1"test 2015"
line2"test
2015"
line3"test 2020"
line4"test
2017"
应转变为:

line1"test 2015"
line2"test2015"
line3"test 2020"
line4"test2017"
使用GNU awk: 这是最直接的方法。用作记录分隔符

NR % 2 == 0 {             # in every other record (those inside quotes)
  gsub(/\n/, "")          # remove the newlines
}
{ 
  printf("%s%s", $0, RT)  # then print the line terminated by the same thing
                          # as in the input (to avoid an extra quote at the
                          # end of the output)
}
RT是一个GNU扩展,这就是为什么它需要gawk

使用sed 使用sed进行此操作的困难在于引号之间可能有两条换行符,例如

line2"test
123
2015"
这使得在条件之后只获取一行变得脆弱。因此:

sed '/^[^"]*"[^"]*$/ { :a /\n.*"/! { N; ba; }; s/\n//g; }' filename
即:

/^[^"]*"[^"]*$/ {   # When a line contains only one quote
  :a                # jump label for looping
  /\n.*"/! {        # until there appears another quote
    N               # fetch more lines
    ba
  }
  s/\n//g           # once done, remove the newlines.
}
作为一个单行程序,这需要GNU sed,因为BSD sed对分支指令的格式很挑剔。但是,应该可以将代码的扩展形式放入一个文件中,比如foo.sed,并使用BSD sed运行sed-f foo.sed filename

请注意,此代码假定在开始引用之后,下一行中包含一个引用的内容仅包含该引用。如果需要的话,解决这个问题的方法是

sed ':a h; s/[^"]//g; s/""//g; /"/ { x; N; s/\n//; ba }; x' filename
…但这可能超出了sed应该合理处理的范围。它的工作原理如下:

:a           # jump label for looping
h            # make a copy of the line
s/[^"]//g    # isolate quotes
s/""//g      # remove pairs of quotes
/"/ {        # if there is a quote left (number of quotes is odd)
  x          # swap the unedited text back into the pattern space
  N          # fetch a new line
  s/\n//     # remove the newline between them
  ba         # loop
}
x            # swap the text back in before printing.
使用非GNU awk 在awk中,每行多个引号的情况比在sed中更容易处理。上面的GNU awk代码是隐式执行的;对于非GNU awk,需要多做一点,但也不可怕:

awk -F '"' '{ n = 0; line = ""; do { n += NF != 0 ? NF - 1 : 0; line = line $0 } while(n % 2 == 1 && getline == 1) print line }' filename
主要技巧是用作字段分隔符,以便字段的数量告诉我们行中有多少引号。然后:

{
                                       # reset state
  n = 0                                # n is the number of quotes we have
                                       # seen so far
  line = ""                            # line is where we assemble the output
                                       # line

  do {
    n += NF != 0 ? NF - 1 : 0;         # add the number of quotes in the line
                                       # (special handling for empty lines
                                       # where NF == 0)
    line = line $0                     # append the line to the output
  } while(n % 2 == 1 && getline == 1)  # while the number of quotes is odd
                                       # and there's more input, get new lines
                                       # and loop

  print line                           # once done, print the combined result.
}
使用GNU awk: 这是最直接的方法。用作记录分隔符

NR % 2 == 0 {             # in every other record (those inside quotes)
  gsub(/\n/, "")          # remove the newlines
}
{ 
  printf("%s%s", $0, RT)  # then print the line terminated by the same thing
                          # as in the input (to avoid an extra quote at the
                          # end of the output)
}
RT是一个GNU扩展,这就是为什么它需要gawk

使用sed 使用sed进行此操作的困难在于引号之间可能有两条换行符,例如

line2"test
123
2015"
这使得在条件之后只获取一行变得脆弱。因此:

sed '/^[^"]*"[^"]*$/ { :a /\n.*"/! { N; ba; }; s/\n//g; }' filename
即:

/^[^"]*"[^"]*$/ {   # When a line contains only one quote
  :a                # jump label for looping
  /\n.*"/! {        # until there appears another quote
    N               # fetch more lines
    ba
  }
  s/\n//g           # once done, remove the newlines.
}
作为一个单行程序,这需要GNU sed,因为BSD sed对分支指令的格式很挑剔。但是,应该可以将代码的扩展形式放入一个文件中,比如foo.sed,并使用BSD sed运行sed-f foo.sed filename

请注意,此代码假定在开始引用之后,下一行中包含一个引用的内容仅包含该引用。如果需要的话,解决这个问题的方法是

sed ':a h; s/[^"]//g; s/""//g; /"/ { x; N; s/\n//; ba }; x' filename
…但这可能超出了sed应该合理处理的范围。它的工作原理如下:

:a           # jump label for looping
h            # make a copy of the line
s/[^"]//g    # isolate quotes
s/""//g      # remove pairs of quotes
/"/ {        # if there is a quote left (number of quotes is odd)
  x          # swap the unedited text back into the pattern space
  N          # fetch a new line
  s/\n//     # remove the newline between them
  ba         # loop
}
x            # swap the text back in before printing.
使用非GNU awk 在awk中,每行多个引号的情况比在sed中更容易处理。上面的GNU awk代码是隐式执行的;对于非GNU awk,需要多做一点,但也不可怕:

awk -F '"' '{ n = 0; line = ""; do { n += NF != 0 ? NF - 1 : 0; line = line $0 } while(n % 2 == 1 && getline == 1) print line }' filename
主要技巧是用作字段分隔符,以便字段的数量告诉我们行中有多少引号。然后:

{
                                       # reset state
  n = 0                                # n is the number of quotes we have
                                       # seen so far
  line = ""                            # line is where we assemble the output
                                       # line

  do {
    n += NF != 0 ? NF - 1 : 0;         # add the number of quotes in the line
                                       # (special handling for empty lines
                                       # where NF == 0)
    line = line $0                     # append the line to the output
  } while(n % 2 == 1 && getline == 1)  # while the number of quotes is odd
                                       # and there's more input, get new lines
                                       # and loop

  print line                           # once done, print the combined result.
}
对于sed:

sed '/[^"]$/{N;s/\n//}' file
输出:

line1"test 2015" line2"test2015" line3"test 2020" line4"test2017" 搜索//不带单个字符的^end$行。仅适用于这些行{}:将下一行N追加到sed的模式空间当前行,并使用sed的搜索和替换s///在模式空间中查找现在嵌入的换行符\N并替换为零。

使用sed:

sed '/[^"]$/{N;s/\n//}' file
输出:

line1"test 2015" line2"test2015" line3"test 2020" line4"test2017"
搜索//不带单个字符的^end$行。仅适用于这些行{}:将下一行N追加到sed的模式空间当前行,并使用sed的search and replace s///在模式空间中查找现在嵌入的换行符\N并替换为nothing。

这可能适用于您的GNU-sed:

sed -r ':a;N;s/^([^\n"]*"[^\n"]*)\n/\1 /;ta;P;D' file
这将用一个空格替换两行之间的换行符,其中第一行仅包含一个双引号


注意:空格也可以被删除,但数据表明是这样的。

这可能适用于GNU用户:

sed -r ':a;N;s/^([^\n"]*"[^\n"]*)\n/\1 /;ta;P;D' file
这将用一个空格替换两行之间的换行符,其中第一行仅包含一个双引号

注意:空间也可能会被移除,但数据表明它会被移除