【问题标题】:Inserting underscores in strings using sed使用 sed 在字符串中插入下划线
【发布时间】:2017-01-14 18:58:45
【问题描述】:

我正在尝试使用 sed 在非空白字符字符串的每个大写字母之前插入 _,除非它位于开头。 (我想转换驼峰式的字符串,偶尔包含几个相邻的大写字母甚至标点符号。)

期望的行为:

输入:

AaAaAa AAA AAA

输出:

Aa_Aa_Aa A_A_A A_A_A

我尝试使用以下命令:

sed -e "s/\(\S\)\([[:upper:]]\)/\1_\2/g"

但它在上述输入中的最后两个字符串上失败了,产生了这个:

Aa_Aa_Aa A_AA A_AA

我真的不明白为什么。

我使用的是 GNU sed 4.2.2。

【问题讨论】:

    标签: regex sed


    【解决方案1】:

    我假设您的示例输入错误,因为 Aa Aa Aa 给您提供的替换没有任何作用。而且它也不是骆驼案标识符。应该是AaAaAa,对吗?

    如果是这样,那么您可以让sed 执行您需要的操作,方法是使其循环直到不再发生替换:

    echo "AaAaAa AAA AAA" | sed -e ':x;s/\([^[:space:]_]\)\([[:upper:]]\)/\1_\2/g;tx' 
    

    生产

    Aa_Aa_Aa A_A_A A_A_A 
    

    【讨论】:

      【解决方案2】:

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

      sed -r 'y/_/\n/;s/[[:upper:]]/_&/g;s/\b_//g;y/\n/_/' file
      

      将所有_ 转换为唯一的替代方案。在大写字符前面插入_。删除任何前导的_。重新转换原来的_'s。

      如果您一开始就没有任何领先的_,那么这就足够了:

      sed -r 's/[[:upper:]]/_&/g;s/\b_//g' file
      

      【讨论】:

        【解决方案3】:

        问题在于,对于单个 s///g,正则表达式匹配不能重叠(并且更早替换的结果不会被考虑用于进一步匹配)。

        AAA,第一个匹配是

        AAA
        ^^
        | \
        \1 \2
        

        替换后,我们有A_AA,“当前位置”在最右边的两个A之间:

        A _ A A
             ^
             next match attempt starts here
        

        然后我们再次尝试匹配,但我们已经用完了字符。 \S 匹配最后一个 A,但仅此而已:之后没有大写字符。

        要完成这项工作,我们必须以某种方式将中间的 A 匹配为第一次替换的 \2 和第二次替换的 \1,我不知道如何使用 sed .

        (使用 perl 会很容易,因为您可以使用后视/前瞻,它不会在匹配中包含周围的文本:perl -pe 's/(?<=\S)(?=[[:upper:]])/_/g'

        【讨论】:

        • 我也很怀疑。我会尝试使用 perl。
        • 你不需要去 perl 但你需要澄清你的要求,因为现在还不清楚你想要做什么。请参阅@BenjaminW 在您的问题下的评论。
        猜你喜欢
        • 2018-05-20
        • 1970-01-01
        • 2017-08-02
        • 1970-01-01
        • 1970-01-01
        • 2020-02-11
        • 1970-01-01
        • 1970-01-01
        • 2022-01-03
        相关资源
        最近更新 更多