代码之家  ›  专栏  ›  技术社区  ›  the_eraser

bash-sed(或其他)替换前锚定双空格和尾随不可打印字符

  •  0
  • the_eraser  · 技术社区  · 9 年前

    我有以下形式的行

    line="  this is a line with 2 leading spaces and a trailing control char^M"
    

    我想将这里由^M表示的2个前导空格和尾随控制字符都替换为空。

    echo "${line}" | sed 's/^[[:space:]]*//' | tr -dc '[:print:]'
    echo "${line}" | sed 's/^[[:space:]]*//' | sed 's/[^[:print:]]//'
    

    这两种方法都有效。我也尝试过

    echo "${line}" | sed 's/^[[:space:]]*|[^[:print:]]//'
    

    但这行不通。

    为什么最后一个表达式不起作用?
    如何通过对sed的一次调用和一个正则表达式来实现这一点?
    例如,在效率方面,首选的解决方案是什么?避免许多次壳更好吗?
    有更好的解决方案吗?

    2 回复  |  直到 9 年前
        1
  •  2
  •   melpomene    9 年前
    sed 's/^[[:space:]]*|[^[:print]]//'
    

    不起作用,因为 | 完全匹配。“Or”拼写为 \| 在sed中。(和 [:print] 应该是 [:print:] ).

    但这仍然不够,因为默认情况下sed只替换第一次出现;你需要 /g 替换所有出现的标志:

    sed 's/^[[:space:]]*\|[^[:print:]]//g'
    

    但您的原始正则表达式可能会产生一些意想不到的后果: [[:space:]] 匹配换行符,因此如果输入是一个或多个完整的行,它将删除所有空行,而不仅仅是它们的内容。为了防止这种情况,请使用 [[:blank:]] 而是:

    sed 's/^[[:blank:]]*\|[^[:print:]]//g'
    
        2
  •  0
  •   anubhava    9 年前

    这个单一的sed应该可以:

    sed 's/^[[:blank:]]*//; s/[[:cntrl:]]*$//' <<< "$line"
    this is a line with 2 leading spaces and a trailing control char