在 GNU Sed 中将第一个替换为 1),将第二个替换为 2),...

在 GNU Sed 中将第一个替换为 1),将第二个替换为 2),...

伪代码是以下内容的延续这个答案

gsed 's/|/1)/g' 's/|/2)/2g' 's/|/3)/3g' 's/|/5)/4g' 's/|/5)/5g' 
<input.csv >output.csv

这当然是行不通的。我感兴趣的是如何gsed管理这样的循环。

如何gsed扩展到这样的循环?

答案1

对于上面的情况,你可以这样做:

gsed 's/|/1)/; s/|/2)/; s/|/3)/; s/|/4)/; s/|/5)/'

例子:

$ echo '| | | | |' | sed 's/|/1)/; s/|/2)/; s/|/3)/; s/|/4)/; s/|/5)/'
1) 2) 3) 4) 5)

如果您可以提前估计|一行中的最大数量并s/|/N)/相应地添加,则此方法有效。

如果您无法估计|一行上的最大数量,仍然可以使用 来完成gsed,使用保持缓冲区中的计数器,并使用这个聪明的装置作者:布鲁诺·海布尔。但实际的实现有点棘手,因此我将其留给受虐狂精明的读者。

当然,最简单的方法是使用awk

awk '{ cnt = 0; while(sub(/\|/, ++cnt ")")); print }'

证明:

$ echo '| | | | |' | awk '{ cnt = 0; while(sub(/\|/, ++cnt ")")); print }'
1) 2) 3) 4) 5)

答案2

另一个 sed:

sed -n '1x;1s/^/12345/;1x;G;:t
        s/|\(.*\n)\(.\)/\2)\1/;tt
P'    <infile >outfile

但可能awk更适合这里。

一个更为复杂的解决方案:

鉴于您的其他问题的输出......

Question ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n
Que|stion ipsun; option 1 | option 2 | option 3 | option 4 | ... | option n

...并将其传递给...

sed '   s/^/!/;/|/s/\(.*;\)*[^|]*/&\
|/g;    s/.*\(\n\).*/::::::\1&\1::/' |
nl  -d:: -hp^\) -s\)\              |
sed -e' /./{ s/^ *!//;P;d;:n' -e'};N;/\n$/!bn
        s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g;D'

...要得到...

Question ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)
Que|stion ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)

我想我会打破它...

sed '   s/^/!/;/|/s/\(.*;\)*[^|]*/&\
)/g;    s/.*\(\n\).*/::::::\1&\1::/' |..

……是第一阶段。这为 准备输出nl

nl在标准实用程序中具有独特的功能 -(其中大多数将整个输入流视为单个内聚单元)- 因为它可以逻辑上通过分隔输入文件部分nl将输入分为标头,身体, 和页脚对于每个逻辑页它的。对于每页的三个部分,用户可以指定不同的数字风格对于每个,并且对于每个逻辑页用户可以收到新线路数数

有了sed上面我做的:

  • s/^/!/
    • 如果不出意外,这可以确保s 的节定界符不会意外出现在输入中,但这也将用作在处理的另一侧nl修剪 的前导空白的标记。nl
  • /|/s...
    • 这只尝试将替换应用于明确匹配至少一个管道的行|
  • ...s/\(.*;\)*[^|]*/&\n|/g
    • 这对可以匹配任何内容的模式应用全局替换(甚至什么也没有)而是一个|管道,后面有时没有;分号。
      • 因为\(.*;\)*被匹配*零次或多次,所以大多数时候它匹配空字符串。但是,匹配器第一次在包含至少一个分号的行上应用子表达式时;,会有效地跳过从行首到最后一个分号的整个模式空间范围。
      • 这样做的目的是避免匹配[^|]*出现的任何子字符串分隔分号,从而跳过问题整个字符串的一部分。
    • 对于此模式的每次出现,它都会被替换为&自身,并附加一个附加的\n|
  • s/.*\(\n\).*/::::::\1&\1::/
    • 这会将至少包含一个 \newline 的任何模式空间替换为六个冒号,然后是我们捕获的\1\newline,然后是&它本身,然后是我们捕获的\1\newline,然后是两个冒号。
    • 我将使用字符串::作为nl-d分隔符。这些字符串之一开始nl 页脚部分,其中三个字符串标记一个标头- 和一个新的逻辑页面。
    • nl将要仅有的如果分隔符单独出现在一行上,则可以识别该分隔符。

...此时数据流看起来像...

:::::
!问ipsun;选项1
||选项2
||选项3
||选项4
|| ...
||选项n
|
::
:::::
!问题|stion ipsun;选项1
||选项2
||选项3
||选项4
|| ...
||选项n
|
::

...现在我们可以通过...

...|nl -d:: -hp^\) -s\)\ |...
  • -d::
    • 这指定了::分隔符字符串。
    • nl将在输出中用空行替换-d输入中的每个分隔符字符串。
      • nl将在其输出行的开头插入数字,或者在未编号的行的开头插入空格以匹配其数字字符串的长度。
      • 因此,其输出中唯一空白的行是那些曾经是其分隔符字符串的行。
  • -hp^\|
    • 这是一个-h领导者风格意义对与正则表达式模式匹配的所有行进行编号
    • nl将在一个标头发生在仅包含的行之间的每个行序列的状态::::::另一个只包含::
    • 默认nl号码仅有的身体各部分并没有编号标头或者页脚根本不。
  • -s\)\
    • 这是一个分隔符字符串,它将nl插入到它编号的每行的行头和它之前插入的数字之间。

...此时数据流看起来像...

        !问ipsun;选项1
     1) ||选项2
     2) ||选项3
     3)||选项4
     4) || ...
     5)||选项n
     6)|


        !问题|stion ipsun;选项1
     1) ||选项2
     2) ||选项3
     3)||选项4
     4) || ...
     5)||选项n
     6)|

...最后我们可以用...来处理这个问题

sed -e' /./{s/^ *!//;P;d;:n' -e '};N;/\n$/!bn
        s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g;D'
  • /./{...
    • 在任何包含至少一个字符的行上,这都会开始一个以匹配为中心的函数。
    • 后面可能有几个命令,但仅适用于首先与函数父地址匹配的模式空间。
  • ...{s/^ *!//
    • nl在这里,我们从匹配行的头部修剪所有插入的空格和插入的刘海。
  • P;d;:n
    • P会打印到\n模式空间中的第一个 ewline。
    • 然后d删除模式空间。
    • 然后定义分支标签:n
    • 从现在开始,我们只处理以空白行开头的一系列行。
  • N
    • 这会拉入Next 输入行并将其附加到\newline 字符后面的模式空间。
  • /\n$/!bn
    • 虽然模式空间不$以 ewline 结尾(如果ext 行为空,\n则会如此) ,但我们始终回到标签 - 堆叠输入。Nb:n
  • s/[0-9 ]*\n *\([^;|)]*) |*\)|/ (\1/g'
    • 这是g局部替换。
    • 它取代了每个序列...
      • *零个或多个[0-9 ]字符
      • 接下来是\newline
      • 随后是*零个或多个<空格>
      • 后跟*零个或多个^非冒号或管道字符
      • 后面跟着一个右)括号
      • 可能后面跟着一个|管道
      • 肯定后面跟着一个|管道
      • 仅包含^非冒号/管道字符、右括号和可能的管道。
  • D
    • 现在我们D删除\n模式空间中的第一个行(这是第一个字符,因为该序列以空行开始)并将其余部分发送回脚本顶部,以P在下一个新周期中修剪和打印空格和爆炸。

最终结果是:

Question ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)
Que|stion ipsun; option (1) | option (2) | option (3) | option (4) | ... (5) | option n (6)

相关内容