Как мне остановить Sed от добавления дополнительных символов новой строки


17

Я запускаю следующие 2 sedкоманды. Первый добавляет символы новой строки, где я хочу их, второй также добавляет символы новой строки, где я хочу их, НО также добавляет дополнительный в конце файла, где раньше его не было.

sed -e 's|\<LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_1.xml > ${XMLDIR}/statement_tmp_2.xml

sed -e 's|\</LIST_G_STATEMENT>|&\
|g' ${XMLDIR}/statement_tmp_2.xml > ${XMLDIR}/statement_tmp_3.xml

Использование od -cвсех трех файлов дает следующий результат.

Statement_tmp_1.xml (нет \nв конце файла)

1314700    T   A   T   E   M   E   N   T   >   <   /   L   I   S   T   _
1314720    G   _   S   T   A   T   E   M   E   N   T   >   <   /   G   _
1314740    S   E   T   U   P   >   <   /   L   I   S   T   _   G   _   S
1314760    E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1314777

Statement_tmp_2.xml (нет \nв конце файла)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >   <   /   G
1314740    _   S   E   T   U   P   >   <   /   L   I   S   T   _   G   _
1314760    S   E   T   U   P   >   <   /   A   R   X   S   G   P   O   >
1315000

Statement_tmp_3.xml ( \nв конце файла - откуда он взялся?)

1314700    S   T   A   T   E   M   E   N   T   >   <   /   L   I   S   T
1314720    _   G   _   S   T   A   T   E   M   E   N   T   >  \n   <   /
1314740    G   _   S   E   T   U   P   >   <   /   L   I   S   T   _   G
1314760    _   S   E   T   U   P   >   <   /   A   R   X   S   G   P   O
1315000    >  \n
1315002

Я использую AIX 5.3

По сути, я либо хочу, чтобы он прекратил добавлять дополнительные \n, либо нашел способ их удаления.


Просто вопрос: почему вы используете буквальный символ новой строки в шаблоне подстановки, если вы могли бы использовать его s|...|&\n|так же хорошо?
Джозеф Р.

1
@JosephR. \nс правой стороны не является портативным.
Стефан Шазелас

@StephaneChazelas Это странно. Это CR против CRLF?
Джозеф Р.

2
Файл, который не заканчивается символом новой строки, не является текстовым файлом, поэтому поведение с текстовыми утилитами на них не определено . Используйте perlили другой инструмент, который может иметь дело с двоичными данными.
Стефан Шазелас

4
@JosephR. Нет, \<LF>это традиционный и POSIX способ добавить символ LF. \nобычно заменяет nсимвол во всем, кроме GNU sed.
Стефан Шазелас

Ответы:


10

Вы должны считать себя счастливчиком, когда AIX sedдобавил недостающие символы новой строки.

Непустой файл, который не заканчивается символом новой строки, не является текстовым файлом (по крайней мере, согласно определению текстового файла в POSIX), поскольку текстовый файл должен содержать строки, а строки (не слишком long) последовательность символов оканчивается символом перевода строки, поэтому поведение текстовых утилит, подобных sedописанным, не определено и на практике варьируется от реализации к реализации.

В некоторых sedреализациях эти ложные символы были бы удалены после последней строки.

AFAIK, xmlфайлы предназначены для того, чтобы быть текстовыми файлами, так что это означает, что это sedпросто исправлено для вас.

Если вам нужно, чтобы этот файл не заканчивался символом новой строки, вы можете использовать perlдругие инструменты, которые могут справиться с нетекстовыми данными.

perl -pe 's|<LIST_G_STATEMENT>|$&\n|g'

1
Завершающий символ новой строка является полезной, если вы ожидаете , чтобы трубы вашего sedвыхода в любую другую стандартную утилиту Unix. Честно говоря, я не замечал, что sedделал это годами , поскольку подстановки команд оболочки Bourne, такие как $(sed 's/bas/replac/' <<<'basement')скрытое сокращение последней строки, если она есть. Но бывают моменты, когда вы определенно не хотите этого; например , манипулируя текстом X буфера обмена с sed. К вашему сведению, GNU sed, если доступно, не добавляет завершающий символ новой строки, если вы используете pего с -nопцией, как описано в этом ответе SE .
TheDudeAbides

0

Вот способ удалить последнюю строку из файла, используя dd:

printf "" | dd  of='/path/to/file' seek=<filesize_in_bytes - 1> bs=1 count=1

Чтобы проверить, заканчивается ли файл новой строкой, вы можете использовать:

tail -c 1 /path/to/file | tr -dc '\n' | wc -c

И чтобы получить размер файла в байтах, используйте:

wc -c < /path/to/file

0

В соответствии с этим руководством AIX IBM tailделает -rEverse - что выглядит довольно круто. Пока ваш файл меньше 20 КБ, должно работать следующее:

tail -r <file | dd bs=1 skip=1 | tail -r >file.new
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.