用下划线分隔特定词,但不使用复数形式

时间:2018-10-20 00:24:41

标签: regex shell sed sh

我最近一直在使用正则表达式处理字符串,但遇到了麻烦。您知道,我正在尝试获取此信息:

chocolatecakes
thecakeismine
cakessurpassexpectation

为此:

chocolate_cakes
the_cake_ismine
cakes_surpassexpectation

但是,当我使用此功能时:

#!/bin/sh

words_array=(is cake)
number_of_times=0

word_underscorer (){
    echo $1 | sed -r "s/([a-z])($2)/\1_\2/g" | sed -r "s/($2)([a-z])/\1_\2/g"
}

for words_to_underscore in "${words_array[@]}"; do

    if [ "$number_of_times" -eq 0 ]; then
        first=`word_underscorer "chocolatecakes" "$words_to_underscore"`
        second=`word_underscorer "thecakeismine" "$words_to_underscore"`
        third=`word_underscorer "cakessurpassexpectation" "$words_to_underscore"`
    else
        word_underscorer "$first" "$words_to_underscore"
        word_underscorer "$second" "$words_to_underscore"
        word_underscorer "$third" "$words_to_underscore"
    fi

    echo "$first"
    echo "$second"
    echo "$third"
done

我明白了:

chocolate_cake_s
the_cake_ismine
cake_ssurpassexpectation

我不确定如何解决此问题。

3 个答案:

答案 0 :(得分:1)

根据显示的内容,您可以执行以下操作:

sed -r -e "s/($2)/_\1_/g"  -r -e "s/($2)_s|^($2)(_*)/\1s\2_/g" -r -e "s/^_|_$//g"

那应该返回以下结果:

chocolate_cakes
the_cake_ismine
cakes_surpassexpectation

这里的想法是消除的过程;这并不是说此方法没有潜在的问题-希望您能理解我的意思。每个sed操作均用数字标记,以帮助您了解发生了什么。

sed命令在数组上起作用,该数组以“ is”开始,然后以“ cake”开头:

1. is  ->  _is_
2. is_s or is_  ->  iss or is_
3. _is_  ->  is

1. cake  ->  _cake_
2. cake_s or cake_  ->  cakes or cake_
3. _cake_  ->  cake

字符串一个

1. chocolatecakes -> chocolate_cake_s
2. chocolate_cake_s -> chocolate_cakes_
3. chocolate_cakes_ -> chocolate_cakes

字符串两个

1. thecake_is_mine -> the_cake_ismine
2. the_cake_ismine -> no change
3. the_cake_ismine -> no change

字符串

1. cakessurpassexpectation -> _cake_ssurpassexpectation
2. _cake_ssurpassexpectation -> _cakes_surpassexpectation
3. _cakes_surpassexpectation -> cakes_surpassexpectation

因此,您可以在此处查看数组的“ is”部分可能存在的问题;如果它以某种方式最终在操作编号2上变成“ is_s”,则在sed操作期间可能会以不希望的方式分解。在这里,您将需要测试字符串的多个组合以确保您已经涵盖了所有不需要的情况。完成后,您可以返回并根据需要优化模式,甚至可以进一步找到优化方式的方式,以允许您使用更少的管道命令。

答案 1 :(得分:1)

如果将单词写到文件(words)中,则可以执行以下操作:

sed -e 's/\('$(sed ':l;N;s/\n/\\|/;bl' words )'\)/\1_'/g -e 's/_$//' input

这给您:

chocolate_cakes
the_cake_ismine
cakes_surpassexpectation

重点是构造此sed命令:

sed -e s/\(chocolate\|cake\|the\|cakes\)/\1_/g -e s/_$// input

答案 2 :(得分:0)

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

sed -r 's/\B([^_])\B(cakes?|is)\B/\1_\2/g;s/(cakes?|is)\B([^_])\B/\1_\2/g' file

如果特定单词在另一个单词内,并且该单词之前/之后的字符不是下划线,则在该单词的前面/后面插入下划线。