根据下一行的第一个字符连接行

根据下一行的第一个字符连接行

我正在根据下一行寻找客场联络线。到目前为止,我看到的唯一方法是创建一个 shell 脚本,该脚本将逐行读取并执行以下操作:

while read line
    if $line does not start with "," and $curr_line is empty 
        store line in curr_line
    if $line does not start with "," and $curr_line is not empty
        flush $curr_line to file
        store $line in $curr_line
    if $line starts with "," append to $curr_file, flush to file empty curr_line
done < file

所以我试图了解是否可以使用 sed 甚至 grep 和重定向来实现。该文件的规则很简单。最多且只有一行以“,”开头的行需要附加到上一行。

前任:

line0
line1
line2
,line3
line4
line5
,line6
line7
,line8
line9
line10
line11

结果文件将是

line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11

答案1

我会做:

awk -v ORS= '
  NR>1 && !/,/ {print "\n"}
  {print}
  END {if (NR) print "\n"}' < file

也就是说,如果当前行不以 开头,则仅打印分隔上一行的换行符,

任何状况之下,我不会使用while read循环

答案2

这是 的一个经典用例sed,如中所述Sed 单行解释,第一部分:文件间距、编号以及文本转换和替换,40. 如果前一行以等号“=”开头,则在前一行后面追加一行。,(对 for进行了明显的修改=

sed -e :a -e '$!N;s/\n,/,/;ta' -e 'P;D' file
line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11

答案3

您需要做的就是读取文件并删除逗号之前的所有换行符:

$ perl -0777pe 's/\n,/,/g' file
line0
line1
line2,line3
line4
line5,line6
line7,line8
line9
line10
line11

答案4

这是一个完美的的用例ex

如果您还没有听说过,ex是 的前身vi,例如vi,它是由 POSIX 指定并且基本上*随处可用。

ex实际上是为文件设计的编辑,但您也可以在不保存更改的情况下使用它。


打印更改,不保存到文件:

printf '%s\n' 'g/^,/-j!' %p | ex file.txt

进行更改并保存到文件:

printf '%s\n' 'g/^,/-j!' x | ex file.txt

解释:

我使用该printf命令作为脚本文件编辑的包装器ex。这种形式的优点是,在任何失败时(例如,您传递的命令不是真正的命令,或者您尝试寻址不存在的行号),该命令只是退出(不保存任何更改)而不是等待其他输入。

您可以通过运行命令本身来查看传递给printf的确切命令:exprintf

$ printf '%s\n' 'g/^,/-j!' %p
g/^,/-j!
%p

好吧,这些命令有什么作用?

嗯,g是“全局”命令,它在“缓冲区”(文件)中与正则表达式匹配的所有行上运行以下命令^,(行开头后跟逗号)。

本例中的命令是-j!.是-一个地址,表示在该地址上执行以下命令以前的行到当前行。 (换句话说,在这条线上以逗号开头的行。)

j用于“连接”,它将该行与下一行连接起来。感叹号 ( !) 禁止使用空格字符来分隔原始行和与其连接的行。

%是一个地址,意思是“整个缓冲区”,p意思是“打印”。

x表示保存更改并退出。

正如我所说,这是一个完美的的用例示例ex


*Windows 除外。 :P

相关内容