Chciałbym usunąć wszystkie początkowe i końcowe spacje i tabulatory z każdego wiersza wyniku.
Czy istnieje proste narzędzie, do trim
którego mógłbym przesłać dane wyjściowe?
Przykładowy plik:
test space at back
test space at front
TAB at end
TAB at front
sequence of some space in the middle
some empty lines with differing TABS and spaces:
test space at both ends
Odpowiedzi:
lub krócej:
Przycinałby początkowe i końcowe spacje lub znaki tabulacji 1, a także ściskał sekwencje tabulatorów i spacji w jednym miejscu.
Działa to, ponieważ kiedy przypisujesz coś do jednego z pól ,
awk
odbudowuje cały rekord (zgodnie z drukowaniemprint
), łącząc wszystkie pola ($1
, ...,$NF
) zOFS
(domyślnie spacja).1 (i ewentualnie inne puste znaki w zależności od ustawień regionalnych i
awk
implementacji)źródło
awk '{$1=$1}1'
;
wymagana jest w standardowej składni awkecho -e 'foo \t bar' | awk '{$1=$1};1'
echo ' hello ' | xargs
Polecenie można tak skondensować, jeśli używasz GNU
sed
:Przykład
Oto powyższe polecenie w akcji.
Możesz użyć,
hexdump
aby potwierdzić, żesed
polecenie poprawnie usuwa żądane znaki.Klasy postaci
Możesz także użyć nazw klas znaków zamiast dosłownie wymieniać takie zestawy
[ \t]
:Przykład
Większość narzędzi GNU korzystających z wyrażeń regularnych (regex) obsługuje te klasy.
Używanie ich zamiast zestawów literalnych zawsze wydaje się marnowaniem miejsca, ale jeśli martwisz się, że Twój kod jest przenośny lub masz do czynienia z alternatywnymi zestawami znaków (myśl międzynarodowymi), prawdopodobnie będziesz chciał użyć nazw klas zamiast.
Bibliografia
źródło
[[:space:]]
nie jest to równoważne[ \t]
z ogólnym przypadkiem (Unicode itp.).[[:space:]]
prawdopodobnie będzie znacznie wolniejszy (ponieważ w Unicode jest o wiele więcej rodzajów białych znaków niż tylko' '
i'\t'
). To samo dotyczy wszystkich pozostałych.sed 's/^[ \t]*//'
nie jest przenośny. W rzeczywistości POSIX wymaga nawet usunięcia sekwencji spacji, ukośnika odwrotnego lubt
znaków, i to właśnie robi GNUsed
, gdyPOSIXLY_CORRECT
jest w środowisku.sed 's/^[[:blank:]]*//;s/[[:blank:]]*$//'
Jak sugeruje Stéphane Chazelas w przyjętej odpowiedzi, możesz teraz
utworzyć skrypt
/usr/local/bin/trim
:i nadaj temu plikowi uprawnienia do wykonywania:
Teraz możesz przekazać każde wyjście
trim
na przykład:(w przypadku komentarzy poniżej: użyłem tego wcześniej:
while read i; do echo "$i"; done
co również działa dobrze, ale jest mniej wydajne)
źródło
while read -r line
do zachowania backslashy i nawet wtedy ... . Jeśli chodzi o ogromne pliki / szybkość, naprawdę wybrałeś najgorsze rozwiązanie. Nie sądzę, żeby było tam coś gorszego. Zobacz odpowiedzi na pytanie: Dlaczego używanie pętli powłoki do przetwarzania tekstu jest złą praktyką? w tym mój komentarz do ostatniej odpowiedzi, w której dodałem link do testu porównawczego prędkości. Tesed
tutaj odpowiedzi są perfekcyjnie IMO i znacznie lepiej niżread
.-
i po nich kombinacjami 1 lub więcej znaków e, E lub n i / lub zawiera znaki NUL. Również linia nieskończona po ostatniej nowej linii zostanie pominięta.xargs bez argumentów to robi.
Przykład:
źródło
xargs
nie uda się dostarczyć, jeśli dane wejściowe zawierają odwrotne ukośniki i pojedyncze cudzysłowy.echo
wywołań. Niektóre implementacje echa przetwarzają również opcje i / lub ukośniki odwrotne ... Działa to również tylko w przypadku wprowadzania jednowierszowego.Jeśli czytasz wiersz w zmiennej powłoki,
read
rób to już, chyba że instrukcja inaczej .źródło
read
. Jeśli więccat file | while read i; do echo $i; done
echo "$i"
aby zobaczyć prawdziwy efektread
Jeśli przechowujesz linie jako zmienne, możesz użyć bash do wykonania zadania:
usuń wiodące białe znaki z ciągu:
usuń końcowe białe znaki z łańcucha:
usuń wszystkie białe znaki z łańcucha:
źródło
Aby usunąć wszystkie początkowe i końcowe spacje z danej linii dzięki narzędziu „potokowemu”, mogę zidentyfikować 3 różne sposoby, które nie są całkowicie równoważne. Różnice te dotyczą odstępów między słowami linii wejściowej. W zależności od oczekiwanego zachowania dokonasz wyboru.
Przykłady
Aby wyjaśnić różnice, rozważmy następujący fikcyjny wiersz wejściowy:
tr
tr
jest naprawdę prostym poleceniem. W takim przypadku usuwa wszelkie spacje lub znaki tabulacji.awk
awk
usuwa spacje wiodące i tailing i ściska do pojedynczego spacji co spację między słowami.sed
W takim przypadku
sed
usuwa spacje początkowe i końcowe bez dotykania spacji między słowami.Uwaga:
W przypadku jednego słowa w wierszu
tr
wykonuje zadanie.źródło
[:space:]
zamiast polecenia [: blank:] dla poleceniatr
, takiego jak :,... | tr -d [:space:]
aby usunąć również nowe wiersze. (patrz:man tr
)sed jest doskonałym narzędziem do tego:
Możesz go użyć w swoim przypadku, albo wstawiając tekst, np
lub działając na nim „inline”, jeśli twój
sed
jest GNU:ale zmiana źródła w ten sposób jest „niebezpieczna”, ponieważ może być niemożliwa do odzyskania, gdy nie działa poprawnie (lub nawet gdy działa!), więc najpierw wykonaj kopię zapasową (lub użyj,
-i.bak
który ma tę zaletę, że może być przenośny na niektóre BSDsed
) !źródło
polecenie translacji działałoby
źródło
Jeśli ciąg, który próbujesz przyciąć, jest krótki i ciągły / ciągły, możesz po prostu przekazać go jako parametr do dowolnej funkcji bash:
źródło