【问题标题】:Linux delete spaces after a character in a lineLinux删除一行字符后的空格
【发布时间】:2026-01-20 16:10:02
【问题描述】:

在 Linux 中,如果我有一个包含以下条目的文件:

我的号码是 = 1234; #这是一个随机数

我可以使用 sed 或其他任何东西将“#”之后的所有空格替换为“+”,以便输出如下所示:

我的号码是 = 1234; #this+is+a+随机+数字

【问题讨论】:

    标签: linux replace sed


    【解决方案1】:

    一种使用awk的方式:

    awk -F# 'OFS=FS { gsub(" ", "+", $2) }1' file.txt
    

    结果:

    My Number is = 1234; #This+is+a+random+number
    

    编辑:

    看完下面的cmets,如果你的文件中包含多个#,可以试试这个:

    awk -F# 'OFS=FS { for (i=2; i <= NF; i++) gsub(" ", "+", $i); print }' file.txt
    

    【讨论】:

    • 1 是一个计算结果为真的表达式,导致打印当前行。这是{print} 的快捷方式。
    • 虽然这个答案是 awk 的一个很好的例子,但我不能 100% 确定它符合 OP 的要求。如果行中还有另一个# 怎么办?
    • for (i=2;i&lt;=NF;++i) gsub(" ", "+", $i) 替换gsub(" ", "+", $2),它将处理任意数量的# 字符
    • 另外,1 技巧对于代码高尔夫来说很不错,但总的来说,我认为在卷发中使用简单的; print 会更清晰。
    • @ghoti,Point 指出。我对 OP 的输入做了一些假设。
    【解决方案2】:

    效率不高,但是:

    perl -pe '1 while (s/(.*#[^ ]*) /\1+/);'
    

    【讨论】:

      【解决方案3】:

      您可以在纯 shell 中执行此操作...

      $ foo="My Number is = 1234; #This is a random number"
      $ echo -n "${foo%%#*}#"; echo "${foo#*#}" | tr ' ' '+'
      My Number is = 1234; #This+is+a+random+number
      $ 
      

      将此数据捕获到变量中以供进一步使用留给读者作为练习。 :-)

      请注意,这也可以承受行上的多个 # 字符:

      $ foo="My Number is = 1234; #This is a # random number"
      $ echo -n "${foo%%#*}#"; echo "${foo#*#}" | tr ' ' '+'
      My Number is = 1234; #This+is+a+#+random+number
      $ 
      

      或者,如果您希望创建一个变量而不是通过tr 进行管道传输:

      $ echo -n "${foo%%#*}#"; bar="${foo#*#}"; echo "${bar// /+}"
      My Number is = 1234; #This+is+a+#+random+number
      

      最后,如果您不介意带有管道的子外壳,您可以这样做:

      $ bar=$(echo -n "$foo" | tr '#' '\n' | sed -ne '2,$s/ /+/g;p' | tr '\n' '#')
      $ echo "$bar"
      My Number is = 1234; #This+is+a+#+random+number
      $
      

      为了好玩,这里有一个简短的awk 解决方案:

      $ echo $foo | awk -vRS=# -vORS=# 'NR>1 {gsub(/ /,"+")} 1'
      My Number is = 1234; #This+is+a+#+random+number
      #$ 
      

      注意尾随的 ORS。我不知道是否可以避免使用最终记录分隔符。我想你可以通过head -1 将上面的行通过管道来摆脱它,假设你只处理一行输入数据。

      【讨论】:

      • 我认为要使用 awk,您必须按照 steve 的建议执行 for 循环。
      【解决方案4】:

      这是另一个perl one-liner:

      echo 'My Number is = 1234; #This is a random number' \
      | perl -F\# -lane 'join "#", @F[1,-1]; s/ /+/g; print $F[1], "#", $_'
      
      • -F 指定如何将字符串拆分为 @F 数组。
      • -an 将标准输入包装为:
      while (<>) {
        @F = split('#');
        # code from -e goes here
      }
      

      【讨论】:

      • 如果有额外的# 字符,它也会中断。试试看:'My Number is = 1234; #This is a random # number 看看。
      • 对的忘记了分隔符,很快就会修复它。
      • 该修复程序保留了第一个分隔符,但对我发布的备用字符串仍然没有帮助。
      【解决方案5】:

      这可能对你有用(GNU sed):

      echo 'My Number is = 1234; #This is a random number' | 
      sed 's/#/\n&/;h;s/.*\n//;y/ /+/;H;g;s/\n.*\n//'
      My Number is = 1234; #This+is+a+random+number
      

      【讨论】:

      • +1 - 太好了,我希望有人能用保持缓冲区来证明这一点。 :) 唉,在 BSD sed 中,如果有第二个 # 在线,它会严重损坏。 (但你确实提到了 GNU,所以你保持 +1!)
      • @ghoti 谢谢,我很惊讶第二个# 会导致问题(即使对于BSD)。通常\n 是其他 sed 的错误。您能否在翻译中的替换命令中添加g