【问题标题】:Replace leading whitespace with sed (or similar)用 sed (或类似的)替换前导空格
【发布时间】:2012-03-02 14:20:41
【问题描述】:

我想用相同数量的其他字符替换文件每一行的前导空格或制表符(为简单起见,我们使用 _)。

例如

foo bar
 foo bar
  line 3

变成

foo bar
_foo bar
__line 3

请注意,非领先的空白不受影响,否则这很容易!我怀疑这仍然很容易,但我错过了诀窍。

【问题讨论】:

  • 制表符是否被替换为单个“_”,还是足以填写制表位?

标签: regex bash unix sed


【解决方案1】:

@SiegeX 的解决方案不适用于 Mac OS X Lion 上的系统 sed。这是一种解决方法:

eval sed "$(for i in $(seq 40 -1 1); do
                  echo -n "-e 's/^$(for j in $(seq 1 $i);
                      do echo -n ' ';
                  done)/$(for j in $(seq 1 $i);
                      do echo -n '_';
                  done)/' "; done)"

动态生成选项

...
-e 's/^       /_______/g' \
-e 's/^      /______/g' \
-e 's/^     /_____/g' \
-e 's/^    /____/g' \
-e 's/^   /___/g' \
-e 's/^  /__/g' \
-e 's/^ /_/g'

【讨论】:

    【解决方案2】:

    这对你有用:

    sed ':a;s/^\([[:space:]]*\)[[:space:]]/\1_/;ta' file
    

    示例

    $ sed ':a;s/^\([[:space:]]*\)[[:space:]]/\1_/;ta' <<<$'foo bar\n foo bar\n\t\tline 3\n _ x'
    foo bar
    _foo bar
    __line 3
    __ x
    

    【讨论】:

    • 如果一行已经以一个或多个下划线开头,后跟空格,这会在不应该的地方添加下划线。不过,它相对容易抢救:sed '/^[[:space:]]/{:a;s/\(_*\)[[:space:]]/\1_/;ta;}'.
    • @JonathanLeffler 谢谢,很好的电话,更新了答案。在s 命令中仍然需要^ 锚点,以防止单词之间的空格变成下划线。
    • 转录我修改后的sed 脚本时出现错误。 :( 有时很难把所有事情都做好。
    • 您不需要在正则表达式中排除前导下划线,您只需查找空格:{:a;s/^\([[:space:]]*\)[[:space:]]/\1_/;ta}
    • 当前版本还是有点破;像' _ x' 这样的东西会变成'___x' 而不是'__ x'。 (格伦杰克曼的建议可以解决这个问题。)
    【解决方案3】:

    这可能对你有用:

    sed '/^\s\+/!b;h;s///;x;s/\S.*//;s/./_/g;G;s/\n//' <<<$'foo bar\n foo bar\n\t\tline 3'
    foo bar
    _foo bar
    __line 3
    

    将初始制表符扩展为空格,然后扩展为下划线:

    expand -i <<<$'foo bar\n foo bar\n\t\tline 3' |
    sed '/^\s\+/!b;h;s///;x;s/\S.*//;s/./_/g;G;s/\n//'
    foo bar
    _foo bar
    ________________line 3
    

    【讨论】:

      【解决方案4】:

      你还好吗?使用 Perl 单线?你可以写:

      perl -pe 's/^([ \t]+)/"_" x length $1/e'
      

      (在标准输入上的文件中进行管道传输,或者在命令末尾指定文件名)。

      编辑添加:William Pursell 在上面的评论中询问您是否要“用单个 '_' 替换选项卡,或者足以填写一个制表位”。上面的命令将用单个下划线替换选项卡。如果您想填写一个制表位,最简单的方法是使用expand 实用程序,它将制表符转换为空格,然后将输入传递给 Perl:

      expand -i | perl -pe 's/^([ \t]+)/"_" x length $1/e'
      

      (在标准输入上的文件中进行管道传输,或者在 expand 部分的末尾指定文件名,就在 | 字符之前)。

      【讨论】:

      • 在这种情况下不能使用 perl,但无论如何都支持一个可行的解决方案,它显示了一个有趣的(并且可能比 sed 更有效)的解决方案。
      【解决方案5】:

      您可以使用此正则表达式来获取前导空格或制表符

      (^\s+)
      

      但是用下划线替换它,我忍不住因为我没有 bash 经验

      【讨论】:

        猜你喜欢
        • 2014-02-04
        • 2016-05-02
        • 2012-09-14
        • 2016-12-05
        • 2013-12-28
        • 2012-08-25
        • 2014-06-22
        • 2011-09-30
        • 1970-01-01
        相关资源
        最近更新 更多