Разделение определенных слов подчеркиванием, но не множественное число - PullRequest
0 голосов
/ 20 октября 2018

Я недавно работал с регулярным выражением над строками и наткнулся на препятствие.Вы видите, я пытаюсь получить это:

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

Iполучите это:

chocolate_cake_s
the_cake_ismine
cake_ssurpassexpectation

Я не уверен, как это исправить.

Ответы [ 3 ]

0 голосов
/ 20 октября 2018

Если вы пишете слова в файл (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
0 голосов
/ 20 октября 2018

Это может сработать для вас (GNU sed):

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

Вставить подчеркивание перед / после определенного слова, если конкретное слово находится внутри другого слова, а символ перед / после конкретного слова неподчеркивание.

0 голосов
/ 20 октября 2018

На основании того, что вы показали, вы можете сделать что-то вроде:

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";возможно, он может быть поврежден, возможно, нежелательным образом во время операции sed, если каким-то образом он станет «is_s» в операции № 2. Здесь вы захотите протестировать несколько комбинаций ваших строк, чтобы убедиться, что вы 'Мы рассмотрели все возможные сценарии, которые вам не нужны.После того, как вы это сделаете, вы можете вернуться и уточнить шаблоны по мере необходимости, или даже дальше найти способы оптимизировать вещи таким образом, чтобы вы могли использовать команды с меньшим количеством каналов.

...