awk 命令:如果行不以字符开头,请在行之前删除换行符

awk command: if line doesn't starts with a character remove new line on before line

提问人:Luca L 提问时间:12/20/2022 更新时间:12/22/2022 访问量:401

问:

尝试使用 awk 命令来实现此规则:如果行不以“O|”或“A|”或“S|”开头我想删除 before 行上的换行符

我在输入中有这个文件(输入.txt)

O|field1|field2
O|field1|
field2
A|field1|
field2
S|field1|
field2
O|field1|field2
O|field1|field2
O|field1|
field2
A|field1|
field2
S|field1|
field2
O|field1|field2

我想要这个输出

O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2

执行此代码

awk '/^O\|/ || /^A\|/ || /^S\|/ {printf "%s", $0; next} 1 {print}' input.txt > output.txt

它返回

O|field1|field2O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2O|field1|field2O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2

有人可以帮我吗?

字符串 UNIX AWK 数据操作

评论


答:

4赞 anubhava 12/20/2022 #1

这应该对你有用:awk

awk -F'|' 'NF==3 && $3 == "" {p = $0; next}
      {print (NF == 1 ? p $1 : $0); p = ""}' file

O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
3赞 Ed Morton 12/20/2022 #2

像这样测试记录布局的东西可能比测试字段的值更适合你:

$ awk -v RS='([^|]*[|]){2}[^|]*\n' '{$0=RT; gsub(/\n/,""); print}' file
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2

上面使用 GNU awk for multi-char RS 将一条记录定义为 3 个以 s 分隔并以换行符结尾的字段,然后在打印之前从每条记录中删除任何换行符。|

3赞 The fourth bird 12/20/2022 #3

您似乎只遇到缺少最后一个字段的问题。

如果 是字段分隔符,您可以检查第 3 个字段是否不为空并打印整行。|

打印上一行加上当前行(如果字段 1 不是)或AOS

awk -F'|' '{
  if($1 !~ /^[AOS]$/) { print p $0; next }
  if ($3!="") print $0
  p = $0
}' file

输出

O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
4赞 RavinderSingh13 12/20/2022 #4

使用您显示的示例,请尝试以下代码。awk

awk '
BEGIN{FS=OFS="|"}
!/\|/ {
  print val,$0
  val=""
  next
}
$0~/\|$/ && NF==3{
  val=$0
  next
}
1
' Input_file
1赞 RARE Kpop Manifesto 12/20/2022 #5
{m,g,n}awk NF=NF RS= OFS=\| FS='[|]\n'
{  g,n}awk NF=NF RS= OFS=\| FS='\\|\n' 
{m    }awk NF=NF RS= OFS=\| FS='\|\n' 
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2

评论

2赞 The fourth bird 12/20/2022
有趣的解决方案,您能解释一下这是如何工作的吗?做什么,你能把它放在开头吗?NF=NF
1赞 RARE Kpop Manifesto 12/21/2022
@Thefourthbird :与其他人使用的方法相同,但您可以安全地在控制台终端中输入,不加引号。s 按反斜杠的方式接受命令行赋值,而 and 将它们视为主代码中的任何双引号字符串,因此需要双反斜杠,正如您在 的 2 个差异变体中看到的那样。如果你把任何东西放在它的左边,你还必须添加标志前缀,例如.在主代码之后执行此操作允许跳过该部分,但这些部分.....NF = NF$1=$1mawkgawknawkFSNF=NF-v-v OFS=…
1赞 RARE Kpop Manifesto 12/21/2022
.....在所有部分之后(如果有),但在 .设置为空白意味着所有输入块之间没有完全为零长度的空行都会立即得到处理,我只是交换了 和 的角色,并用于修复格式问题。因此,这些解决方案是为自然界中不连续输送的输入而设计的。BEGIN { }NR == 1RSFSRSFS + OFS
1赞 RARE Kpop Manifesto 12/21/2022
@Thefourthbird : 实际上是一个有问题的形式::::::::::::::::::::: ::::::::::::::::::: ::::::::::::::::: :::::::::::::::::::::::::::::::: :::::::::::::: :::::::::::::::::::它什么都不打印,因为实际上是一个空字符串,并且驻留在 中。赋值与 doing 相同,这意味着该模式正在将空字符串计算为布尔值,因此没有执行 的默认操作。 修复了该问题,请记住,由于为零,它仍会跳过空行$1 = $1echo ' abc xyz ' | mawk '$1=$1' FS='[ ]+'$1"abc"$2$1 = ""FALSE{ print }NF=NFNF
3赞 karakfa 12/20/2022 #6

另一种解决方案

awk -v RS="" '{gsub("\\|\n","|")}1' file

O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2
O|field1|field2
O|field1|field2
A|field1|field2
S|field1|field2
O|field1|field2

将文件视为一个长流,并删除管道后面的换行符。

1赞 Walter A 12/21/2022 #7

使用 GNU :sed

sed -rz 's/\|\n([^OAS])/\|\1/g' input.txt
0赞 Martin York 12/22/2022 #8

怎么样:

awk '/^[OAS]\|/ {if (l){print l}l=$0;next} {l=l $0} END {print l}' inputFile

该变量表示我们正在构建的线。l

如果输入以特殊字符开头,则打印(如果它不是空)。否则,开始建立阵容。在处理完所有行以打印出 的最新版本后运行。lENDl