У меня есть вход, который выглядит следующим образом:
Austin, Ashley D
Bender, Isaiah J
Здесь я пытаюсь сократить имя до «,», а затем добавить первую букву второго имени.
Например, вышеупомянутыми двумя будут Остина и Бендери. Кто-нибудь может помочь, пожалуйста.
Вы выразили заинтересованность в решении этой проблемы с 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
. Проблема, которую вы представили, просто достаточно сложна, чтобы мотивировать меня использовать более сложный (и, следовательно, более сложный) инструмент, чем базовые инструменты обработки текста. Поскольку вы, вероятно, можете найти способ сделать это с помощью этих инструментов, я, конечно, не виню вас, если вы это сделаете! Но я думаю, что это все еще может быть полезно для будущих, даже более сложных проблем.
Предлагаемое решение с использованием 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 и других, но жемчужное решение более элегантно и уместно.