SED - удаление строки, за которой следует LineFeed (\ n) - PullRequest
8 голосов
/ 15 ноября 2011

Не могу найти подходящее выражение sed для удаления слова, за которым следует строка возврата (\ n)

Тестовый файл:

line1\n
line2\n
line3mark\n
line4\n
line5\n

и я хочу удалить все вхождения метки \ n, в этом случае:

line1\n
line2\n
line3line4\n
line5\n

искали и могут использовать:

sed 's/\n//g' test.file  to remove ALL \n's

но

sed 's/mark\n//g' test.file does not work

Странно, но в интерактивном режиме s / mark \ n // g работает нормально в vi.

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

Большое спасибо.

Ответы [ 8 ]

6 голосов
/ 15 ноября 2011

Для реальных переводов строки используйте:

sed -e ':a; /mark$/ { N; s/mark\n//; ba; }'

Все строки, оканчивающиеся знаком, объединяются со следующей, а теперь середина \ n удаляется.

Если в конце строки есть буквальная строка \n, вам нужно экранировать \ как \\n.

5 голосов
/ 15 ноября 2011

Это должно сделать трюк:

sed -i ':a;N;$!ba;s/mark\n//g' file

Объяснение:

;    command separator within sed
:a   a label, like in C/C++
N    appends the next line to the pattern space
$!ba repeats the N command for all lines but the last line

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

Когда вы делаете что-то вроде

sed -i 's/mark\n//' file

, строки копируются в пространство образца одна за другой.

:a;N;$!ba добавляет каждую строку в пространство образца.

Затем пространство шаблона может быть обработано за один проход, удаляя любой mark\n, здесь важна опция g для global, поскольку она просит sed не останавливаться на первом подходящем шаблоне.

2 голосов
/ 16 ноября 2011

Я видел тег awk, так что мы идем.

Если \n - это «возврат строки», awk может присоединиться к строке, заканчивающейся «mark», следующей строкой.

$> awk '/mark$/ { sub(/mark$/,""); getline t; print $0 t; next }; 1' ./text 
line1
line2
line3line4
line5
1 голос
/ 16 ноября 2011

ответов уже много, sed и awk.

Я добавляю еще один, с помощью awk, просто покажу, что awk может сделать это с помощью более короткой команды:

awk 'gsub(/mark$/,""){printf $0;next;}1' input

тест:

kent$  echo "line1
line2
line3mark
line4
line5"|awk 'gsub(/mark$/,""){printf $0;next;}1'

выход:

line1
line2
line3line4
line5

не знаю, действительно ли это требуется ОП.

1 голос
/ 16 ноября 2011

Если вы можете использовать awk, вы можете сделать

awk '
    /mark$/ {sub(/mark$/, ""); hold = hold $0; next}
    {print hold $0; hold = ""}
    END {if (hold) print hold}
'
0 голосов
/ 26 ноября 2016
awk '{sub(/line4/,"line3line4")}!/mark/' file

line1\n
line2\n
line3line4\n
line5\n
0 голосов
/ 16 ноября 2011

Это может работать для вас:

sed -e '1{h;d};H;${x;s/mark\n//g;p};d' test.file
0 голосов
/ 15 ноября 2011

Просто используйте следующую команду

sed -e "{:q;N;s/mark\n//g;t q}" test.file
...