Как заменить каждое второе вхождение слова в текстовом файле - PullRequest
0 голосов
/ 10 мая 2018

В файле с именем sample.txt у меня есть следующий текст:

Однажды есть черепаха и кролик. Кролик был быстрым, черепаха была медленной. Кролик издевался над черепахой. Однажды кролик бросил вызов черепахе на гонку. Черепаха приняла просьбу кролика. Кролик был самоуверенным. Кролик думал выиграть гонку. Кролик быстро побежал. Потом кролик устал. Кролик хотел отдохнуть. Так кролик спал под елкой. Черепаха продолжала идти и выиграла гонку.

Как заменить каждое второе вхождение от rabbit до hare с помощью команд Unix?

Ответы [ 2 ]

0 голосов
/ 10 мая 2018

Когда ввод занимает одну строку (или вы счастливы считать от 1 в начале каждой строки) и хотите игнорировать заглавную букву Кролик, вы можете использовать это решение: Сначала замените всех кроликов одним символом, которому может соответствовать sed.
Замени второго кролика-персонажа и восстанови других кроликов.

sed -r 's/rabbit/\r/g; s/(\r[^\r]*)\r/\1hare/g; s/\r/rabbit/g' sample.txt

Редактировать, Дополнительное объяснение:
Когда входной файл является чистым файлом в стиле Unix (без окончаний MS-DOS \ r \ n), мы знаем, что символ \r уникален. После sed -r 's/rabbit/\r/g каждый кролик представлен \r (буква r на самом деле не короткая, первая буква rabbit, но первая из return).
Теперь вы хотите найти последовательности <rabbit><not-a-rabbit><rabbit>, в нашей новой записи это последовательность \r[^\r]*\r, где [^\r]* обозначает любую последовательность символов без символа кролика.
Когда мы нашли 2 кроликов, мы хотим вспомнить первого кролика с не кроличьими персонажами. В sed вы можете запомнить согласованную последовательность с \(..\) или использовать опции -r и (..). Вы можете вспомнить первую ячейку памяти (у нас есть только одну) с \1, в этом случае первый кролик \r и не-кроличьи символы. Второй кролик \r заменен на hare.
После замены второго \r (глобального в строке, то есть каждого второго), мы хотим преобразовать \r кроликов в строку rabbit.

Больше возможностей
Если ваш входной файл содержит более 1 строки, вы можете захотеть что-то другое С одним кроликом на первом и одним кроликом на второй линии, как вы можете поймать второго кролика? Перед выполнением вышеуказанной команды sed вам необходимо перенести ваш входной файл в 1 строку. После этого вы хотите восстановить окончания строк, поэтому вам нужно будет заменить окончания строк специальным символом. Обычно я бы использовал \r для этого, но этот символ зарезервирован для кроликов. Символ \v возможен, в результате чего

tr '\n' \v' < sample.txt | 
   sed -r 's/rabbit/\r/g; s/(\r[^\r]*)\r/\1hare/g; s/\r/rabbit/g' | 
   tr '\v' '\n'

Если вы также хотите заменить заглавных Кроликов, мы можем переставить этих Кроликов в \a.
Вы можете запросить любого кролика (большого или маленького) с помощью [\r\a], что сделает команду на один уровень более сложной:

tr '\n' \v' < sample.txt | 
sed -r 's/rabbit/\r/g; s/Rabbit/\a/g; 
        s/([\r\a][^\r\a]*)[\r\a]/\1hare/g;
        s/\r/rabbit/g; s/\a/Rabbit/g' |
tr '\v' '\n'

Если вы хотите заменить заглавного Кролика \a на заглавный Hare, команда станет еще более сложной (вам нужен еще один специальный символ).
Я хочу использовать \x01 для обозначения аббата [Rr] для изменения.

tr '\n' \v' < sample.txt | 
   sed -r 's/rabbit/\r/g;
       s/Rabbit/\a/g;
       s/([\r\a][^\r\a]*)([\r\a])/\1\x01\2/g;
       s/\x01\r/hare/g;
       s/\x01\a/Hare/g;
       s/\r/rabbit/g; s/\a/Rabbit/g' |
tr '\v' '\n'
0 голосов
/ 10 мая 2018

$ sed 's / [Rr] abbit / hare / 2' sample.txt

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