Как определить конец строки с помощью sed

15

Я ищу способ выполнить замену только тогда, когда последний символ является новой строкой, используя sed .

Например:

lettersAtEndOfLine

заменено, но это не так:

lettersWithCharacterAfter&

Так sedкак не работает с переводами строки, это не так просто, как

$ sed -E "s/[a-zA-Z]*\n/replace/" file.txt

Как это можно сделать?

Мэтью Д. Шолфилд
источник

Ответы:

21

При использовании стандарта sedвы никогда не увидите новую строку в тексте, прочитанном из файла. Это потому, что sedчитает строку за строкой, и, следовательно, нет новой строки в конце текста текущей строки в sedпространстве образца. Другими словами, sedчитает данные с разделителями новой строки, и разделители не являются частью того, что sedвидит скрипт.

Регулярные выражения можно закрепить в конце строки, используя $(или в начале, используя^ ). Привязка выражения в начале / конце строки вынуждает его совпадать именно там, а не где-нибудь в строке.

Если вы хотите заменить что-либо, совпадающее с шаблоном [A-Za-z]*в конце строки, чем-то, то закрепите шаблон следующим образом:

[A-Za-z]*$

... заставит его совпадать в конце строки и нигде больше.

Однако, поскольку [A-Za-z]*$также ничего не совпадает (например, пустая строка присутствует в конце каждой строки), вам необходимо принудительно сопоставить что-либо , например, указав

[A-Za-z][A-Za-z]*$

или

[A-Za-z]\{1,\}$

Таким образом, ваша командная строка sed будет

$ sed 's/[A-Za-z]\{1,\}$/replace/' file.txt

Я не использовал -Eпереключатель здесь, потому что он не нужен. С его помощью вы могли бы написать

$ sed -E 's/[A-Za-z]+$/replace/' file.txt

Это вопрос вкуса.

Кусалананда
источник
Комментарии не для расширенного обсуждения; этот разговор был перенесен в чат .
Кусалананда
3
sed "s/[a-zA-Z]*$/replace/" input.txt > result.txt

Или длинный сложный ненужный путь:

Я узнал, что это можно сделать, используя sed, с помощью tr. Вы можете назначить другой символ для представления конца строки. Необходимо использовать другой временный символ, в данном случае «». Давайте использовать «~» для обозначения конца строки:

tr '\n' '`' <input.txt >output.txt
sed -i "s/`/~`/" output.txt
tr '`' '\n' <output.txt >result.txt

И затем, чтобы выполнить фактический поиск и замену, используйте «~» вместо «\ n»:

sed -i -E "s/[a-zA-Z]*~/replace/" result.txt

А затем уберите лишний символ в других строках:

sed -i "s/~//" result.txt

Очевидно, что все это можно соединить вместе, что приведет к чему-то вроде:

tr '\n' '`' <input.txt | sed -e "s/`/~`/" | tr '`' '\n' | sed -E -e "s/[a-zA-Z]*~/replace/" | sed "s/~//" > result.txt
Мэтью Д. Шолфилд
источник
3
Не уверен, что я понимаю ... Почему бы вам просто не привязать к концу строки $? напр.s/[a-zA-Z]*$/replace/
don_crissti
1
2 балла: 1) Лучше использовать \+вместо, *так как последний допускает нулевые буквы в конце строки; 2) Вы можете использовать класс персонажа [[:alpha:]]. Итак:sed 's/[[:alpha:]]\+$/replace/' file
Гленн Джекман
@glennjackman Что такое обратный слеш перед плюсом? Разве это не соответствует дополнительному символу?
Мэтью Д. Скоулфилд
1
GNU sed без -rопции использует этот синтаксис регулярного выражения .
Гленн Джекман
0

Из (сломанного) фрагмента кода, который вы разместили, вы, похоже, хотите заменить и новую строку. В этом случае привязка регулярных выражений сама по себе не может вам помочь. Следующее является решением:

sed '/[[:alpha:]]\+$/{N;s/[[:alpha:]]\+\n/replace/}' your_file

Сломано:

  • /[a-zA-Z]\+$/{} означает применять все, что находится внутри фигур, к строкам, которые соответствуют регулярному выражению.
  • Регулярное выражение - это то, которое использует привязку, как видно из вашего собственного ответа , измененное для учета комментариев Гленна Джекмана .
  • Внутри curlies Nозначает «добавить следующую строку в активный буфер» (чтоsed называется «шаблоном пространства»)
  • Наконец, s///заявление является вашей обязательной заменой. Теперь это работает, потому что пространство шаблона содержит две последовательные строки, и поэтому новая строка является его частью.
Джозеф Р.
источник
0

Чтобы найти конец строки, просто используйте $ -sign :

Без привязки конца строки:

sed -n '/pattern/p' file 

Без привязки конца строки:

sed -n '/pattern$/p' file
неизвестный пользователь
источник