В bash / sed, как вы подходите для строчной буквы, за которой следует ЖЕ буква в верхнем регистре? - PullRequest
0 голосов
/ 11 декабря 2018

Я хочу удалить все экземпляры "aA", "bB" ... "zZ" из входной строки.

например,

echo "foObar" |
sed -Ee 's/([a-z])\U\1//'

должен выдать "fbar"

Но синтаксис \ U работает во второй половине (замещающей части) выражения sed - он не может быть разрешен в соответствующем предложении.

У меня проблемы с преобразованием сопоставленного символа в верхнийcase для повторного использования в соответствующем предложении.


Если кто-нибудь может предложить рабочее регулярное выражение, которое можно использовать в sed (или awk), это было бы здорово.

Сценарии решений в чистой оболочке тоже подойдут (я пытаюсь решить проблему таким образом).

Работающие PCRE (Perl-совместимые регулярные выражения) тоже в порядке, но я понятия не имею, как они работают, поэтому было бы неплохо, если бы вы могли дать объяснение, чтобы пойти с вашим ответом.

К сожалению, У меня не установлен Perl или Python на машине, с которой я работаю.

Ответы [ 5 ]

0 голосов
/ 12 декабря 2018

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

sed -r 's/aA|bB|cC|dD|eE|fF|gG|hH|iI|jJ|kK|lL|mM|nN|oO|pP|qQ|rR|sS|tT|uU|vV|wW|xX|yY|zZ//g' file

Программное решение:

sed 's/[[:lower:]][[:upper:]]/\n&/g;s/\n\(.\)\1//ig;s/\n//g' file

Это отмечает все пары символов нижнего регистра, за которыми следует верхний регистрсимвол с предыдущей новой строкой.Затем вообще удалите такой маркер и пары, которые совпадают с обратной ссылкой, независимо от регистра.Любые другие символы новой строки удаляются, оставляя нетронутыми пары, которые не совпадают.

0 голосов
/ 12 декабря 2018

Для этого есть простой лекс,

%option main 8bit
    #include <ctype.h>
%%
[[:lower:]][[:upper:]] if ( toupper(yytext[0]) != yytext[1] ) ECHO;

(это вкладка до #include, уценка теряет их).Просто введите это, например, that.l, а затем make that.Easy-peasy lex's - хорошее дополнение к вашему набору инструментов.

0 голосов
/ 11 декабря 2018

Вот подробное awk решение, так как у OP нет perl или python:

echo "foObar" |
awk -v ORS= -v FS='' '{
   for (i=2; i<=NF; i++) {
      if ($(i-1) == tolower($i) && $i ~ /[A-Z]/ && $(i-1) ~ /[a-z]/) {
         i++
         continue
      }
      print $(i-1)
   }
   print $(i-1)
}'

fbar
0 голосов
/ 11 декабря 2018

Примечание: Это решение (неудивительно) медленное, на основе обратной связи ОП:
"К сожалению, из-за нескольких проходов - это делает его довольно медленным."


Если есть последовательность символов¹, которая, как вы знаете, никогда не появится на входе,
вы можете использовать трехэтапную замену, чтобы выполнить это с помощью sed:
echo 'foObar foobAr' | sed -E -e 's/([a-z])([A-Z])/KEYWORD\1\l\2/g' -e 's/KEYWORD(.)\1//g' -e 's/KEYWORD(.)(.)/\1\u\2/g'

дает вам: fbar foobAr

Объяснение этапов замены:

  • Найдите строчные буквы, за которыми следует ЛЮБАЯ заглавная буква, и замените их обеими буквами в нижнем регистре с КЛЮЧОМ перед ними foObar foobAr-> fKEYWORDoobar fooKEYWORDbar
  • Удалите KEYWORD, за которым следуют два идентичных символа (оба теперь строчные, поэтому обратная ссылка работает) fKEYWORDoobar fooKEYWORDbar -> fbar fooKEYWORDbar
  • Удалите оставшиеся KEYWORD из вывода и преобразуйте второй символ после него обратно в исходную, заглавную версию fbar fooKEYWORDbar -> fbar foobAr

¹ В этом примере я использовал KEYWORDв демонстрационных целях.Один символ или, по крайней мере, более короткая последовательность символов будет лучше / быстрее.Просто убедитесь, что вы выбрали что-то, чего не может быть во входных данных.
² Остальные вхождения - это те, в которых строчные версии букв были не идентичны, поэтому мыдолжны вернуть их обратно в исходное состояние

0 голосов
/ 11 декабря 2018

Вы можете использовать следующее решение Perl:

echo "foObar" | perl -pe 's/([a-z])(?!\1)(?i:\1)//g'

См. онлайн-демонстрацию .

Подробности

  • ([a-z]) - Группа 1: буква ASCII в нижнем регистре
  • (?!\1) - отрицательный прогноз, который не соответствует совпадению, если следующий символ совпадает с захваченным в Группе 1
  • (?i:\1) - тот же символ, что и в группе 1, но в другом случае (из-за предвидения перед ним).

Опция -e позволяет определить код Perl, который будет выполнятьсяКомпилятор и опция -p всегда печатают содержимое $_ каждый раз в цикле.Смотрите подробнее здесь .

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...