sed nie usuwa znaku nowej linii

12

Używam od seddłuższego czasu, ale oto dziwactwo, z którym się spotkałem, którego nie jestem w stanie rozwiązać.

Pozwól mi wyjaśnić mój problem z faktyczną sprawą.


Scena 1

printf "ls" | xclip -selection clipboard
echo "ls" | xclip -selection clipboard

W pierwszym poleceniu printfprzesyłam potokiem dane wyjściowe, aby zostały xclipskopiowane do schowka. Teraz printfinaczej niż echodomyślnie nie wstawia nowej linii. Tak więc, jeśli wkleję tę zawartość do terminala, lsskopiowane polecenie nie uruchomi się automatycznie.

W drugim jest nowy wiersz na końcu, więc wklejenie zawartości schowka powoduje również uruchomienie polecenia w schowku.

To jest dla mnie niepożądane. Tak więc chciałem usunąć nowy wiersz za pomocą sed, ale nie udało się, jak wyjaśniono w poniższej scenie.

Scena # 2

echo "ls" | sed -r 's/\n//g' | xclip -selection clipboard

Treść w schowku nadal zawiera nową linię. Kiedy wkleję go do terminala, polecenie uruchamia się automatycznie.

Próbowałem także usunąć znak powrotu karetki \r. Ale nada. Wygląda na to, że brakuje mi czegoś bardzo ważnego / podstawowego.

Shivams
źródło

Odpowiedzi:

16

sedograniczenia w \newline - są zawsze usuwane na wejściu i ponownie wstawiane na wyjściu. Nie ma nigdy\n charakter ewline w sedprzestrzeni wzorów, które nie występują w wyniku takiej zmiany zostały dokonane. Uwaga: z wyjątkiem GNU sed„s -ztrybie ...

Po prostu użyj tr:

echo ls | tr -d \\n | xclip -selection clipboard

Albo jeszcze lepiej sedcałkowicie zapomnij :

printf ls | xclip -selection clipboard
mikeserv
źródło
Spowoduje to usunięcie wszystkich nowych linii, często w tym generate-text | xclipprzypadku niepożądanych . Ta odpowiedź usuwa tylko ostatnią nową linię.
Tom Hale
7

Wiele narzędzi do przetwarzania tekstu, w tym sed, działa na zawartości linii, z wyjątkiem znaku nowej linii. Pierwszą rzeczą, jaką robi sed podczas przetwarzania linii, jest usunięcie nowej linii na końcu, a następnie wykonanie poleceń w skrypcie i dodanie końcowej nowej linii podczas drukowania. Więc nie będziesz w stanie usunąć nowej linii za pomocą sed.

Aby usunąć wszystkie nowe wiersze, możesz trzamiast tego użyć :

echo "ls" | tr -d '\n' | xclip

Gilles „SO- przestań być zły”
źródło
4

Możesz zastąpić znaki nowej linii w sed, przekazując mu opcję -z .

sed -z 's/\n/ /g'

Strona podręcznika użytkownika Sed:

-z, --null-data oddzielne wiersze znakami NUL

JSON C11
źródło
Spowoduje to usunięcie wszystkich nowych linii, co na ogół nie jest pożądane w tym | xclipprzypadku.
Tom Hale
2

Jeśli po prostu wstawiasz polecenia do schowka

echo -n "ls " | xclip -selection clipboard

Jeśli dodatkowo musisz wykonać bardziej złożone transformacje,

echo "ls  " | perl -pe 's/\n//' | xclip -selection clipboard
JJoao
źródło
Hmm Gładkie rozwiązanie. Myślę, że nadszedł czas, aby przejść do Perla lub Pythona na regex.
shivams,
3
@shivams - perli pythonoba są znacznie wolniejsze niż sedmoże być, gdy są używane poprawnie. Kluczem jest jednak umiejętność prawidłowego korzystania z niego.
mikeserv
@mikeserv - zgadzam się; specjalne dla oneliner sed jest cudowne. Jeśli transformacje staną się bardziej złożone, wolę perl / python / gawk.
JJoao,
1
@JJoa: Twoje preferencje są twoje, ale sedmogą zrobić znacznie więcej niż obsłużyć tylko jedno linijki i prawdopodobnie może to zrobić szybciej niż jakiekolwiek inne wspomniane narzędzia.
mikeserv
1
@mikeserv - raz jeszcze się z tobą zgadzam. Jakiś rok temu miałem system tłumaczący EN-PT napisany w sed (20000 s /.../.../), wygenerowany przez sed! I zadziałało! Później stał się Perl, aby mieć tablice, skróty, funkcje, pakiety i CPAN.
JJoao,
1

Aby usunąć tylko ostatnią nową linię , przeciągnij przez:

sed -z '$ s/\n$//'

sednie doda \0końca do tego strumienia, jeśli ogranicznik jest ustawiony na NULvia -z, natomiast aby utworzyć plik tekstowy POSIX (zdefiniowany jako koniec a \n), zawsze będzie wyświetlał końcowy \nbez -z.

Na przykład:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender

I aby udowodnić, że nie NULdodano:

$ { echo foo; echo bar; } | sed -z '$ s/\n$//' | xxd
00000000: 666f 6f0a 6261 72                        foo.bar

Aby usunąć wiele końcowych znaków nowej linii , przeciągnij przez:

sed -Ez '$ s/\n+$//'
Tom Hale
źródło