Как выполнять поиск, замену и добавление шаблона в конец каждой строки

У меня есть следующий список предметов:

bigBone fishMarket dogCollar ... 

Мне нужно создать двухсимвольное отображение следующим образом:

 bigBone -> bb fishMarket -> fm dogCollar -> dc ... 

Как создать приведенное выше сопоставление с помощью sed ?

Я пробовал что-то вроде:

 sed -i -r 's/^([az]{1})[az]+([AZ]{1})[a-zA-Z]+/ -> \1\L\2/' file 

Я видел этот вопрос , но не уверен, как включить здесь концепцию. Благодарю.

  • Как разбить список имен файлов в наборах 5 ГБ?
  • Заменить текст многострочным шаблоном
  • как grep текст до следующего пространства?
  • Цвет полосы в OS X с BSD sed (или любым другим инструментом)
  • Извлечение текстовых блоков на основе вывода grep
  • sed для сопоставления между совпадающими фигурными фигурными скобками
  • Извлечение определенной информации из журналов
  • Инкремент чисел внутри строк смещением
  • 6 Solutions collect form web for “Как выполнять поиск, замену и добавление шаблона в конец каждой строки”

    Если я правильно вас понимаю, вы хотите сохранить всю строку и просто добавить что-то:

     sed -r 's/^([az]{1})([az]+)([AZ]{1})([a-zA-Z]+)$/\1\2\3\4 -> \1\L\3/' file 

    Редактировать :

    devnull должен был напомнить мне об этом, что есть легкое решение этого:

     sed -r 's/^([az]{1})[az]+([AZ]{1})[a-zA-Z]+/& -> \1\L\2/' file 

    Или, немного более элегантно (чем моя первая попытка):

     sed -r ' h s/^([az]{1})[az]+([AZ]{1})[a-zA-Z]+/ -> \1\L\2/ t append b : append H g s/\n//' file 

    Использование GNU sed:

     sed -r 's/(.)[^[:upper:]]*(.).*/& -> \1\L\2/' inputfile 

    Для вашего ввода это произвело бы:

     bigBone -> bb fishMarket -> fm dogCollar -> dc 

    Чтобы обобщить на fooBarBaz -> fbb , abCdEfGh -> aceg , с помощью GNU sed :

     sed -r 's/(.)(.*)/\1\n\2 -> \L\1/;:1 s/\n([^[:upper:]]*([[:upper:]]))(.*)/\1\n\3\L\2/;t1;s/\n//' 

    У POSIX sed нет \L Таким образом, переносимо, вам придется прибегнуть к использованию y и вручную ввести все символы, которые вы хотите преобразовать в нижний регистр. Что-то вроде:

     LC_ALL=C sed '/^\([[:alpha:]]\).*/{ h;s//\1/;y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;G s/\(.\).\(.\)\(.*\)/\2\ \3 -> \1/;:1 /.*\n[^AZ]*\([AZ]\).*/{h;s//\1/ y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/;G s/^\(.\)\n\(.*\)\n\([^AZ]*[AZ]\)\(.*\)/\2\3\ \4\1/;t1 } s/\n//;}' 

    Вот он с POSIX-совместимым скриптом. Я не знал, что POSIX sed оставляет поведение s///[n]g неуказанным, но, конечно же , это не четкое поведение. Во всяком случае, без него легко справиться – я просто не люблю использовать слишком много обратных ссылок, если это может быть полезно, как правило.

     sed '/^[az]*[AZ].*$/{ h s/\(.\)[^AZ]*/\1/g y/ABCDEFGHIJKLMNOPQRSTUVWXYZ/abcdefghijklmnopqrstuvwxyz/ H ; gs/\n/ -> / }' <<\DATA bigBone fishMarket dogCollar DATA #OUTPUT bigBone -> bb fishMarket -> fm dogCollar -> dc 

    Этот ответ похож на @ devnull's,

     $ sed 's/\(.\).*\([AZ]\).*/& -> \1\L\2/g' file bigBone -> bb fishMarket -> fm dogCollar -> dc 

    Если вы можете использовать perl , попробуйте:

     $ perl -MList::Util=first -F// -aple '$_ .= " -> ".$F[0].lc(first{ord() < 97} @F)' file bigBone -> bb fishMarket -> fm dogCollar -> dc 
    Linux и Unix - лучшая ОС в мире.