我最近一直在使用正则表达式处理字符串,但遇到了麻烦。您知道,我正在尝试获取此信息:
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
我不确定如何解决此问题。
答案 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
如果特定单词在另一个单词内,并且该单词之前/之后的字符不是下划线,则在该单词的前面/后面插入下划线。