首页 > 解决方案 > 用下划线分隔特定单词,但不是复数形式

问题描述

我最近一直在使用正则表达式处理字符串,但遇到了障碍。你看,我试图得到这个:

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

我不知道如何解决这个问题。

标签: regexshellsedsh

解决方案


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

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操作过程中以不希望的方式分解。这是您需要测试字符串的多个组合以确保您已涵盖所有您不想要的可能场景。完成后,您可以根据需要返回并改进模式,甚至进一步找到优化事物的方法,使您可以使用更少的管道命令。


推荐阅读