将多行文件转换为多行文件

将多行文件转换为多行文件

这是我要转换的文件:

john doe  
555-666-333  
[email protected]  
die  
jane doe  
Beverly Hills
444-333-111  
[email protected]  
die  

我希望结果文件是这样的:

john doe,555-666-333,[email protected]  
jane doe,Beverly Hills,444-333-111,[email protected]

该单词die在文件中,我想用它来分隔我的行,这样它们就不会出现在输出中,如上所示。

编辑
我已经更改了文件的格式。前一种格式没有考虑到单词之间的数量可能会变化的事实die

答案1

$ awk -v OFS=',' '/^die$/ { print substr(lines,2); lines=""; next } { lines=lines OFS $0 }' file
john doe,555-666-333,[email protected]
jane doe,Beverly Hills,444-333-111,[email protected]

对于包含逗号的数据,同样的情况也适用(请参阅下面我的答案的末尾)。如果数据包含逗号,您可能需要使用:

awk -v OFS=',' '
    /^die$/ { print substr(lines,2); lines=""; next }
    /,/     { $0=sprintf("\"%s\"", $0 ) }
            { lines=lines OFS $0 }' file

该代码构建了一个由(逗号)lines分隔的字符串。当在一行中找到OFS该单词本身时,输出字符串 in 。当记录的第一个字段附加到字符串时,调用会删除添加在行前面的逗号。带逗号的行的处理方式与我下面的代码相同。dielinessubstr()

使用 GNUawkmawk,但不使用 BSD awk,你也可以这样做

mawk -v RS='\ndie\n' -v FS='\n' -v ORS='\n' -v OFS=',' '{$1=$1;print}' file

这不会为包含逗号的数据生成带引号的字段。

强制在输出之前根据(输出字段分隔符)和(输出记录分隔符)变量$1=$1重新形成awk记录。OFSORS


在更新问题之前回答:

paste -d, - - - - <file

这会产生

john doe,555-666-333,[email protected],die
jane doe,444-333-111,[email protected],die

要删除这些die行(这些是完全没有必要的):

paste -d, - - - - <file | cut -d, -f 1-3

如果原始数据不包含逗号,则上述方法有效。

您还可以die从头开始过滤掉行:

sed '/^die$/d' file | paste -d, - - -

即使原始数据包含逗号,这也可以工作。

如果数据包含逗号,您可能需要对其进行预处理以在这些行周围添加引号:

awk '/^die$/ { next } /,/ { $0=sprintf("\"%s\"", $0 ) } 1' file | paste -d, - - -

给定文件

john doe
555-666-333
[email protected]
die
jane doe
444-333-111
[email protected]
die
Me, myself and I
000-000-000
[email protected]

最后一个命令会生成

john doe,555-666-333,[email protected]
jane doe,444-333-111,[email protected]
"Me, myself and I",000-000-000,[email protected]

答案2

你可以用这样的惯用语来做到这一点awk

$ awk '$1=$1' RS='.die\n' OFS="," FS='\n' file1
john doe,555-666-333,[email protected]
jane doe,Beverly Hills,444-333-111,[email protected]

在上面awk,我们将记录分隔符定义RSdie在文件中用于分隔人员详细信息的条目。

$1=$1强制 awk 使用“,”作为输出字段分隔符重新计算和打印输入字段OFS

PS:当我怀疑文件结尾有问题时,就像\r我用来调用tr删除可能的\r字符一样:tr -d '\r' file1 |awk .....

顺便说一下,你也可以像这样使用 sed:

$ sed -z 's/\n/,/g; s/,die,/\n/g'

通过欺骗 sed 使用空字符作为记录分隔符,这将产生与 awk 相同的输出。

一旦输入文件中不存在真正的空字符,sed 就会将整个输入文件视为一条大记录 == 一条大行。

答案3

这可以使用“sed”编辑器以 POSIX 方式完成

sed -e '
    :a
       $q;N;y/\n/,/
       s/,die$//;t
    ba
' input_file

方法:

  • 设置一个循环并将下一行附加到模式空间中。
    • 命令
  • 将换行符更改为逗号,然后尝试去掉“,die”
    • 是/// s///命令
  • 如果成功,则一切都已准备就绪,无需对此进行进一步处理。
    • t没有标签的命令
  • 否则,回去获取更多,以防万一我们结束了,我们就退出。
    • bq 命令。

我们还可以使用 Perl 来实现此目的:

perl -lne '
    push @A, $_ unless /^die$/;
    print join ",", splice @A if /^die$/ || eof;
' input_file

我们在数组中累积行,直到看到“骰子”行。此时我们通过逗号连接数组内容(也清空数组)。

我们还可以读取文件,然后调用 Perl 来获取结果:

perl -lF'/^die\n/m' -0777nae 'print join ",", split /\n/ for @F' input_file
  • -F'/^die\n/m' 将在正则表达式 BOL die 上将文件拆分为字符串,后跟换行符。
  • -0777 将打开吸吮声。-n应禁用自动打印行和-A将根据-F价值。

相关内容