Jak zatrzymać dodawanie dodatkowych znaków nowej linii

17

Korzystam z następujących 2 sedpoleceń. Pierwszy dodaje znaki nowego wiersza tam, gdzie chcę, drugi także znaki nowego wiersza tam, gdzie chcę, ALE dodaje także dodatkowy znak na końcu pliku, w którym wcześniej go nie było.

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

Użycie od -cwszystkich 3 plików daje następujące wyniki.

statement_tmp_1.xml (brak \nna końcu pliku)

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 (brak \nna końcu pliku)

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 ( \nna końcu pliku - skąd on pochodzi?)

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

Korzystam z systemu AIX 5.3

Zasadniczo chcę albo przestać dodawać dodatkowe \n, albo znaleźć sposób na ich usunięcie.

jonnohudski
źródło
Tylko pytanie: dlaczego używasz dosłownie nowej linii we wzorcu podstawiania, skoro s|...|&\n|równie dobrze mógłbyś użyć ?
Joseph R.
1
@JosephR. \npo prawej stronie nie jest przenośny.
Stéphane Chazelas,
@StephaneChazelas To dziwne. Czy to sprawa CR kontra CRLF?
Joseph R.
2
Plik, który nie kończy się znakiem nowego wiersza, nie jest plikiem tekstowym, więc zachowanie za pomocą narzędzi tekstowych nie jest określone . Użyj perllub innego narzędzia, które może przetwarzać dane binarne.
Stéphane Chazelas,
4
@JosephR. Nie, \<LF>to tradycyjny i POSIXOWY sposób dodawania znaku LF. \nzwykle zastępuje nznak w czymkolwiek innym niż GNU sed.
Stéphane Chazelas,

Odpowiedzi:

11

Powinieneś uważać się za szczęściarza, że ​​AIX seddodał brakujące znaki nowej linii.

Niepusty plik, który nie kończy się znakiem nowej linii, nie jest plikiem tekstowym (przynajmniej zgodnie z definicją pliku tekstowego POSIX), ponieważ plik tekstowy ma zawierać linie, a linie są (niezbyt długi) ciąg znaków zakończony znakiem nowego wiersza, więc zachowanie narzędzi tekstowych takich jak sedna nim jest nieokreślone i w praktyce różni się od implementacji do implementacji.

Niektóre sedimplementacje odrzuciłyby ten fałszywy charakter po ostatniej linii.

AFAIK, xmlpliki mają być plikami tekstowymi, więc oznacza sedto , że właśnie to naprawiłeś.

Jeśli potrzebujesz, aby ten plik nie kończył się znakiem nowej linii, możesz użyć perlinnych narzędzi, które poradzą sobie z danymi nietekstowymi.

perl -pe 's|<LIST_G_STATEMENT>|$&\n|g'
Stéphane Chazelas
źródło
1
Końcowa nowa linia jest pomocna, jeśli spodziewasz się potokować sedwyjście do dowolnego innego standardowego narzędzia uniksowego. Szczerze mówiąc, nie zauważyłem sedtego przez lata , ponieważ podstawienia poleceń powłoki Bourne'a, takie jak $(sed 's/bas/replac/' <<<'basement')ukradkowe przycinanie ostatniej linii, jeśli taka istnieje. Ale chwile, kiedy zdecydowanie tego nie chcesz; np. manipulowanie tekstem schowka X za pomocą sed. FYI, GNU sed, jeśli jest dostępny, nie dodaje kończącego znaku nowej linii, jeśli użyjesz pgo z -nopcją, jak opisano w tej odpowiedzi SE .
TheDudeAbides,
0

Oto sposób na usunięcie ostatniej nowej linii z pliku przy użyciu dd:

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

Aby sprawdzić, czy plik kończy się znakiem nowej linii, możesz użyć:

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

Aby uzyskać rozmiar pliku w bajtach, użyj:

wc -c < /path/to/file
chan
źródło
0

Według tego podręcznika systemu AIX IBM tailrobi -reverse - co wygląda całkiem fajnie. Tak długo, jak plik nie przekracza 20 KB, powinny działać:

tail -r <file | dd bs=1 skip=1 | tail -r >file.new
mikeserv
źródło