Як зупинити 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всіх 3-х файлів дає наступний результат.

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у правій частині руки не є портативним.
Stéphane Chazelas

@StephaneChazelas Це дивно. Це CR та CRLF?
Джозеф Р.

2
Файл, який не закінчується символом нового рядка, не є текстовим файлом, тому поведінка з текстовими утилітами на них не визначена . Використовуйте perlабо інший інструмент, який може працювати з двійковими даними.
Stéphane Chazelas

4
@JosephR. Ні, \<LF>це традиційний та POSIX спосіб додавання символу LF. \nзазвичай замінює nперсонаж нічим іншим, крім GNU sed.
Stéphane Chazelas

Відповіді:


11

Ви повинні вважати себе щасливим, що AIX sedдодав цих відсутніх символів нового рядка.

Непорожній файл, який не закінчується символом нового рядка, не є текстовим файлом (принаймні, відповідно до визначення POSIX текстового файлу), оскільки текстовий файл повинен містити рядки, а рядки є (не занадто- довга) послідовність символів, що закінчується символом нового рядка, тому поведінка текстових утиліт, як sedна ній, не визначено і на практиці змінюється від реалізації до реалізації.

Деяка sedреалізація відкинула б цей хибний характер після останнього рядка.

AFAIK, xmlфайли мають на увазі текстові файли, так що це означає, що sedвиправили це для вас.

Якщо вам потрібно, щоб цей файл не закінчувався символом нової лінії, ви можете використовувати perlінші інструменти, які можуть впоратися з нетекстовими даними.

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

1
Новий рядок, що закінчується, є корисним, якщо ви очікуєте sedпередавати свій вихід у будь-яку іншу стандартну утиліту Unix. Чесно кажучи, я не помічав sedцього роками , оскільки підстановки команд Борна оболонками люблять $(sed 's/bas/replac/' <<<'basement')несамостійно обрізати останній рядок, якщо такий є. Але бувають випадки, коли ви точно цього не хочете; наприклад , маніпулювання текстом буфера обміну X із sed. FYI, 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робить все -rбеззаперечно - що виглядає досить круто. Поки ваш файл не перевищує 20 Кб, слід працювати наступним чином:

tail -r <file | dd bs=1 skip=1 | tail -r >file.new
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.