【问题标题】:Replace odd and even occurrences of a pattern to another same pattern将奇数和偶数出现的模式替换为另一个相同的模式
【发布时间】:2021-10-04 00:42:12
【问题描述】:

有一个场景,用除以 2 时的商数替换偶数和奇数的反斜杠。

For example
Input: (15 backslashes)
\\\\\\\\\\\\\\\
output: (7 backslashes)
\\\\\\\

Input: (14 backslashes)
\\\\\\\\\\\\\\
output: (7 backslashes)
\\\\\\\

我尝试使用 sed 命令,该命令适用于 4 个反斜杠到 2 个。 sed 's/\\\\/\\/g'

如果有帮助,不胜感激。

【问题讨论】:

  • 变量中有反斜杠字符串吗?例如,如果你有A='\\\\\\\\\\\\\\\' ,那么B=${#A}/2 ; echo ${A:0:$B}
  • 没有。它在一个文件中。

标签: linux unix awk sed


【解决方案1】:

使用 sed:在奇数行中 \ 首先去掉最后一个。然后像你一样替换对:

sed -r 's/((\\\\)*)(\\)?/\1/g;s/\\\\/\\/g'

演示:

$ cat foo.txt
\\\\
\\\
\\
$ sed -r 's/((\\\\)*)(\\)?/\1/g;s/\\\\/\\/g' foo.txt
\\
\
\

【讨论】:

  • 感谢您的时间和帮助。欣赏它。
  • @rowboat 你说得对。 sed 's/\\//;s/\\\\/\\/g' 也是如此。我没看到这个。好的。你也是对的,我的解决方案适用于反斜杠行,但不适用于反斜杠和其他字符串的混合。我刚刚意识到这并没有被 OP 排除在外。 OP 应该接受@Sundeep 更好的答案。
  • @rowboat 我终于意识到将g 标志添加到第一个替代命令可以解决“\\\foo\\\”的问题。我相应地修正了我的答案,但@Sundeep 的答案仍然更优雅,应该是首选。然后是你的,因为紧凑和聪明。
  • @Ranaud Pacalet 如果修改您的命令以仅替换奇数出现,它会起作用吗?即不影响甚至发生的事件。
  • @Sen 如果每行可以出现多次,则很难调整我的解决方案。更喜欢 @Sundeep 提出的更好的解决方案的修改:sed -r 's/((\\+)\2)?\\/\2/g'(如果应该删除单个反斜杠)否则 sed -r 's/(\\+)\1\\/\1/g'
【解决方案2】:

已编辑。试试:

sed 's/\\//; s/\\\\/\\/g'

解释:先去掉一个反斜杠;然后用一个反斜杠替换每一对。第二个命令末尾的 g 表示您必须在整行上重复该操作。反斜杠需要转义。这就是为什么你每次都写两次的原因。

【讨论】:

  • 这是 OP 已经尝试过的。对于 15 个反斜杠输入,它将输出 8 个反斜杠,而不是预期的 7 个。
  • 是的。它不适用于奇数,因为我需要奇数和偶数相同。
  • @RenaudPacalet:PO 没有在命令末尾添加标志 g。感谢您指出错误。我没有正确计算反斜杠的数量。我想我可以解决它。我将编辑我的帖子
【解决方案3】:

使用您显示的示例,请尝试遵循awk 代码。这适用于任意数量的/slashes,并且会给出一半的数字。

awk '
BEGIN{ OFS="" }
{
  val=""
  num=split($0,arr,"")
  till=(int(num/2))
  for(i=1;i<=till;i++){
    val=(val?val OFS:"")arr[i]
  }
  print val
}
'  Input_file

说明:为上述添加详细说明。

awk '                             ##Starting awk program from here.
BEGIN{ OFS="" }                   ##Setting OFS to null here.
{
  val=""                          ##Nullifying val here.
  num=split($0,arr,"")            ##Splitting current line to arr with NULL delimiter.
  till=(int(num/2))               ##getting half of NF(number of fields) in till.
  for(i=1;i<=till;i++){           ##Traversing through fields till value of till.
    val=(val?val OFS:"")arr[i]    ##Creating val here which has array individual element value.
  }
  print val                       ##Printin val here.
}
' Input_file                      ##Mentioning Input_file name here.

【讨论】:

  • 感谢您的时间和帮助。欣赏它。
  • @Sen,欢迎您,我还添加了解决方案的详细说明,干杯。
【解决方案4】:

你可以试试这个awk:

cat file

\\\\\\\\\\\\\\\
\\\\\\\\\\\\\\

# using awk
awk '{print substr($0, 1, int(length($0)/2))}' file

\\\\\\\
\\\\\\\

【讨论】:

    【解决方案5】:

    另一个sed解决方案:

    $ cat ip.txt
    \\\\\\\\
    \\\\\\\
    \\\\\\
    \\\\\
    \\\\
    \\\
    \\
    \
    $ sed -E 's/(\\+)\1\\?/\1/g' ip.txt
    \\\\
    \\\
    \\\
    \\
    \\
    \
    \
    \
    

    (\\+)\1\\? 将反斜杠均分,最后的可选匹配将消耗最后一个反斜杠用于奇数情况。

    如果应该删除单个反斜杠而不是保留,请使用

    sed -E 's/((\\+)\2)?\\?/\2/g'
    

    【讨论】:

    • 只是想知道。是否可以只考虑奇数事件而保持偶数事件不变。 For example Input: (15 backslashes) \\\\\\\\\\\\\\\ output: (7 backslashes) \\\\\\\ Input: (14 backslashes) \\\\\\\\\\\\\\ output: (14 backslashes) \\\\\\\\\\\\\\
    • 在这种情况下,请尝试sed -E 's/(^|[^\\])(\\+)\2\\([^\\]|$)/\1\2\3/g'perl -pe 's/(?&lt;!\\)(\\+)\1\\(?!\\)/$1/g'
    • sed -E 's/(^|[^\])(\\+)\2\([^\]|$)/\1\2\3/g' 不工作对于单个反斜杠,这也很奇怪。 Input: (1 backslash) \ output: (0 backslash) Input: (3 backslashes) \\\ output: (1 backslash) \ Input: (5 backslashes) \\\\\ output: (2 backslashes) \\ Input: (7 backslashes) \\\\\\\ output: (3 backslashes) \\\ and so on...
    • 您可以使用答案中提到的s/((\\+)\2)?\\?/\2/g模型对其进行修改
    【解决方案6】:

    使用 perl 和@Sundeep's ip.txt 文件:

    $ perl -pe 's{(\\+)}{"\\" x int(length($1)/2)}ge' ip.txt
    \\\\
    \\\
    \\\
    \\
    \\
    \
    \
    
    

    用零个反斜杠替换一个反斜杠。

    【讨论】:

      猜你喜欢
      • 2011-11-10
      • 2021-07-21
      • 1970-01-01
      • 2011-05-17
      • 1970-01-01
      • 2013-04-03
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多