Может ли cut оставить только первую букву после запятой и пробела?

У меня есть вход, который выглядит следующим образом:

Austin, Ashley D
Bender, Isaiah J

Здесь я пытаюсь сократить имя до «,», а затем добавить первую букву второго имени.

Например, вышеупомянутыми двумя будут Остина и Бендери. Кто-нибудь может помочь, пожалуйста.

1
задан 19 June 2019 в 00:09

2 ответа

Вы выразили заинтересованность в решении этой проблемы с cut. Должен быть способ сделать это с трубами и некоторой комбинацией cut , tr и (возможно) paste . Но особенно потому, что вы изменяете регистр инициала (например, ведущая буква «А» в Эшли становится конечной буквой «а» в «Остина»), проще использовать что-то более универсальное, чем cut. Я предлагаю однострочник Perl , который может быть этим или чем-то вроде этого, в зависимости, в первую очередь, от того, какие символы вы хотите разрешить в именах:

perl -wpe 's/^(\w+),\s*(\w).*/$1\L$2/' file

, который запускает интерпретатор Perl, с включенными предупреждениями (-w), построчным считыванием ввода, выполнением сценария в каждой строке и выводом результата (-p) и извлечением его сценария из следующего аргумента командной строки (-e). Сам скрипт, s/^(\w+),\s*(\w).*/$1\L$2/, который я цитирую с одинарными кавычками , чтобы оболочка не выполняла свои собственные расширения , состоит из s/pattern/replacement/ ] выражение, которое сопоставляет его входные данные с шаблоном и заменяет совпадение заменой .

В регулярном выражении , ^(\w+),\s*(\w).*:

  • ^ соответствует началу строки.
  • (\w+) соответствует одному или нескольким ( + ) символам слова ( \w , см. Ниже) и захватывает их ( ( ) ] ) в первую группу захвата.
  • , соответствует буквально.
  • \s* соответствует нулю или более ( * ) пробельных символов ( \s ).
  • (\w) соответствует ровно одному символу слова ( \w , см. Ниже) и записывает его ( ( ) ) во вторую группу захвата.
  • .* соответствует нулю или более ( * ) любого символа, который может появиться в строке ( . ). Другими словами, это соответствует остальной части строки.

Затем $1\L$2 приводит к замене всего совпадающего текста (всей строки, предполагая, что соответствует ):

  • $1, содержимое первой группы захвата, без изменений. Это поле, которое должно содержать фамилию человека.
  • \L$2, содержимое второй группы захвата ($2), преобразованное в строчные буквы ( \L ). Это первый символ, который должен содержать имя человека (но в нижнем регистре).

Это может хорошо работать для вас как есть. Но:

  • Возможно, вам придется изменить оба вхождения \w в шаблоне, в зависимости от того, какие символы вы хотите сопоставить в именах. \w соответствует только буквам, цифрам и подчеркиванию (_). Многие имена имеют другие символы, кроме этого, такие как тире и апострофы.
  • Существует также вопрос о том, что считать буквой (которая, хотя иногда и с другими решениями, применима и к более простым инструментам). См. Каков наилучший способ сопоставления только букв в регулярном выражении? Это относится к именам, которые содержат акцентированные буквы, диакритические знаки, которые прикрепляются к буквам, и буквам нелатинских алфавитов.
  • Преобразование дела - более сложная проблема, чем может показаться. Мало того, что разные письменные языки имеют разные буквы, они также имеют разные преобразования для некоторых одних и тех же букв.

Другой простой выбор вместо \w, о котором я могу подумать - разрешить именам содержать что-нибудь отличное от , кроме пробелов или , - может быть достигнуто заменой каждого \w на [^,\S]. [ ] составляют класс символов , ведущий ^ означает, что класс содержит все , но указанные символы (что не связано с его значение вне класса символов), , определяет себя буквально, а \s определяет все пробельные символы.

perl -wpe 's/^([^,\s]+),\s*([^,\s]).*/$1\L$2/' file

Для получения дополнительной информации о регулярных выражениях в Perl см. perldoc perlretut и perldoc perlre . Проблема, которую вы представили, просто достаточно сложна, чтобы мотивировать меня использовать более сложный (и, следовательно, более сложный) инструмент, чем базовые инструменты обработки текста. Поскольку вы, вероятно, можете найти способ сделать это с помощью этих инструментов, я, конечно, не виню вас, если вы это сделаете! Но я думаю, что это все еще может быть полезно для будущих, даже более сложных проблем.

1
ответ дан 19 June 2019 в 00:09

Предлагаемое решение с использованием cut, pipe, tr, paste и (и sed) может быть:

cut -f1 -d, foo >bar; cut -f2 -d" " foo | cut -c1 |tr "A-Z" "a-z" >bar2 ;paste bar bar2|sed -e "s/\x9//g"

, где foo - это файл с вашим вводом. Таким образом, вы можете справиться с задачей с помощью Cut и других, но жемчужное решение более элегантно и уместно.

0
ответ дан 19 June 2019 в 00:09

Другие вопросы по тегам:

Похожие вопросы: