使用shell查找并替换文件中的新行字符和单词

使用shell查找并替换文件中的新行字符和单词,shell,awk,sed,scripting,Shell,Awk,Sed,Scripting,我有一个文件sample.txt,它的内容是 line-1 Generic-text-1 line-2 Generic-text-2 line-3 line-2 Generic-text-1 line-2 Generic-text-2 line-3 我想将文件的内容更改为CSV,以便像下面这样转换内容 line-1,line-2,line-3 line-2,line-2,line-3 我正在尝试使用sed命令,但不能使用新行字符 sed -i 's/\nGeneric-text-1/,/g'

我有一个文件sample.txt,它的内容是

line-1
Generic-text-1 line-2
Generic-text-2 line-3
line-2
Generic-text-1 line-2
Generic-text-2 line-3
我想将文件的内容更改为CSV,以便像下面这样转换内容

line-1,line-2,line-3
line-2,line-2,line-3
我正在尝试使用sed命令,但不能使用新行字符

sed -i 's/\nGeneric-text-1/,/g' sample.txt
sed -i 's/\nGeneric-text-2/,/g' sample.txt

提前感谢

这可能适合您GNU sed:

sed -E ':a;$!N;s/\n\S+\s/,/;ta;P;D' file
聚集行,用逗号替换换行符、第一个字段及其分隔符。当匹配失败时,打印第一行,删除它并重复

更详细的解释是:

-命令行选项扩展regexps。在这种情况下,允许使用速记+而不是\+。 :a是一个占位符a,允许在此点继续执行sed命令,稍后与ta一起使用。 $!N只要当前行不是文件$!,中的最后一行!,将下一行N追加到模式空间中的当前行。模式空间是执行sed命令的缓冲区。 s/\n\s+\s/,/是一个替换命令,在该命令中,a将被替换为一个新行的匹配项,该新行后跟一个或多个非空格字符,后跟一个空格字符,即,附加行开头的一个单词后跟至少一个空格。 ta如果替换成功,则将代码执行跳转到占位符a,即返回2条指令。 P在这一点上,最后一次替换失败,这将打印到并包括模式空间中的第一条换行。 D这将删除模式空间中最多并包括第一个换行符。但是,与重新启动sed循环并将下一行读入模式空间的d命令不同,此命令仅在当前模式空间为空时执行。如果它包含值,它将在第一个sed命令(在本例中为命令a)处恢复。 因此,sed程序会一点一点地删除文件,创建和打印/删除自己制作的行

或在紧要关头:

sed -z 's/\n\S\+ /,/g' file
或:


这可能适用于GNU sed:

sed -E ':a;$!N;s/\n\S+\s/,/;ta;P;D' file
聚集行,用逗号替换换行符、第一个字段及其分隔符。当匹配失败时,打印第一行,删除它并重复

更详细的解释是:

-命令行选项扩展regexps。在这种情况下,允许使用速记+而不是\+。 :a是一个占位符a,允许在此点继续执行sed命令,稍后与ta一起使用。 $!N只要当前行不是文件$!,中的最后一行!,将下一行N追加到模式空间中的当前行。模式空间是执行sed命令的缓冲区。 s/\n\s+\s/,/是一个替换命令,在该命令中,a将被替换为一个新行的匹配项,该新行后跟一个或多个非空格字符,后跟一个空格字符,即,附加行开头的一个单词后跟至少一个空格。 ta如果替换成功,则将代码执行跳转到占位符a,即返回2条指令。 P在这一点上,最后一次替换失败,这将打印到并包括模式空间中的第一条换行。 D这将删除模式空间中最多并包括第一个换行符。但是,与重新启动sed循环并将下一行读入模式空间的d命令不同,此命令仅在当前模式空间为空时执行。如果它包含值,它将在第一个sed命令(在本例中为命令a)处恢复。 因此,sed程序会一点一点地删除文件,创建和打印/删除自己制作的行

或在紧要关头:

sed -z 's/\n\S\+ /,/g' file
或:

使用awk,您可以执行以下操作:

awk -v OFS=, 'NF > 1 {
   printf "%s", OFS $NF
}
NF == 1 {
   if (NR>1)
      print ""
   printf "%s", $1
}
END {
   print ""
}' file
使用awk,您可以执行以下操作:

awk -v OFS=, 'NF > 1 {
   printf "%s", OFS $NF
}
NF == 1 {
   if (NR>1)
      print ""
   printf "%s", $1
}
END {
   print ""
}' file
使用awk,只打印每行的最后一个字。使用逗号分隔符合并成一行,即两个单词行之间的所有单词

awk 'NF==1 && NR!=1{print r; r=""} {r = (r? r "," $NF: $NF)} END {print r}' file
输出:

line-1,line-2,line-3
line-2,line-2,line-3
使用awk,只打印每行的最后一个字。使用逗号分隔符合并成一行,即两个单词行之间的所有单词

awk 'NF==1 && NR!=1{print r; r=""} {r = (r? r "," $NF: $NF)} END {print r}' file
输出:

line-1,line-2,line-3
line-2,line-2,line-3

请您尝试以下,书面和测试显示的样本在GNU awk

awk' 开始{OFS=,} /^线/{ 伊夫瓦尔{ 打印val } 瓦尔=1美元 下一个 } { val=val?val OFS:$NF } 结束{ 伊夫瓦尔{ 打印val } }'输入文件
请您尝试以下,书面和测试显示的样本在GNU awk

awk' 开始{OFS=,} /^线/{ 伊夫瓦尔{ 打印val } 瓦尔=1美元 下一个 } { val=val?val OFS:$NF } 结束{ 伊夫瓦尔{ 打印val } }'输入文件
awk'$0=$NF'sample.txt | paste-d','-?您需要更多详细信息。我们可以猜测,第1行和Generic-text-1之间的区别特征是该行中存在多个非空白字符串,但这只是一个猜测。awk'$0=$NF'sample.txt | paste-d','-?您需要更多详细信息。我们可以猜测,第1行和Generic-text-1之间的区别特征是在该行中存在多个非空白字符串,但这只是一个猜测
如果你能给我解释一下你给出的第一个解决方案的选项:sed-E:a;$!Ns/\n\s+\s/,/;助教;P非常感谢,非常感谢。如果您能向我解释您给出的第一个解决方案的选项,我将不胜感激:sed-E:a;$!Ns/\n\s+\s/,/;助教;P非常感谢,非常感谢。