Kiedy wykonuję polecenia w języku Bash (a ściślej wc -l < log.txt
), dane wyjściowe zawierają po nim łamanie wierszy. Jak się tego pozbyć?
Kiedy wykonuję polecenia w języku Bash (a ściślej wc -l < log.txt
), dane wyjściowe zawierają po nim łamanie wierszy. Jak się tego pozbyć?
Odpowiedzi:
Jeśli oczekiwanym wyjściem jest pojedynczy wiersz , możesz po prostu usunąć wszystkie znaki nowego wiersza z wyniku. Nie jest niczym niezwykłym podłączanie do narzędzia „tr” lub Perla, jeśli jest to preferowane:
wc -l < log.txt | tr -d '\n'
wc -l < log.txt | perl -pe 'chomp'
Możesz także użyć podstawienia polecenia, aby usunąć końcowy znak nowej linii:
echo -n "$(wc -l < log.txt)"
printf "%s" "$(wc -l < log.txt)"
Należy pamiętać, że nie zgadzam się z decyzją PO o wyborze zaakceptowanej odpowiedzi. Uważam, że w miarę możliwości należy unikać używania „xargs”. Tak, to fajna zabawka. Nie, nie potrzebujesz go tutaj.
Jeśli oczekiwane dane wyjściowe mogą zawierać wiele wierszy , musisz podjąć inną decyzję:
Jeśli chcesz usunąć MULTIPLE znaki nowej linii z końca pliku, ponownie użyj podstawienia cmd:
printf "%s" "$(< log.txt)"
Jeśli chcesz ściśle usunąć OSTATNI znak nowej linii z pliku, użyj Perla:
perl -pe 'chomp if eof' log.txt
Zauważ, że jeśli jesteś pewien, że masz końcowy znak nowej linii, który chcesz usunąć, możesz użyć „head” z GNU coreutils, aby wybrać wszystko oprócz ostatniego bajtu. Powinno to być dość szybkie:
head -c -1 log.txt
Ponadto, dla kompletności, możesz szybko sprawdzić, gdzie znajdują się twoje znaki nowej linii (lub inne znaki specjalne) w twoim pliku, używając „cat” i flagi „pokaż wszystko”. Znak dolara wskazuje koniec każdej linii:
cat -A log.txt
tr --delete '\n'
.
| tr -d '\r'
Jednokierunkowa:
wc -l < log.txt | xargs echo -n
echo -n `wc -l log.txt`
IFS
) w jednym miejscu. Przykład echo "a b" | xargs echo -n
:; echo -n $(echo "a b")
. Może to stanowić problem w przypadku użycia.
-e
, będą interpretowane jako opcja echo
. Jest zawsze bezpieczniejszy w użyciu printf '%s'
.
xargs
jest bardzo wolny w moim systemie (i podejrzewam, że dotyczy to również innych systemów), więc printf '%s' $(wc -l log.txt)
może być szybszy, ponieważ printf
zwykle jest wbudowany (również dlatego, że nie ma przekierowania informacji). Nigdy nie używaj backticków, były one przestarzałe w nowszych wersjach POSIX i mają wiele wad.
Istnieje również bezpośrednie wsparcie dla usuwania białych znaków w podstawieniu zmiennych Bash :
testvar=$(wc -l < log.txt)
trailing_space_removed=${testvar%%[[:space:]]}
leading_space_removed=${testvar##[[:space:]]}
trailing_linebreak_removed=${testvar%?}
Jeśli przypiszesz jego wynik do zmiennej, bash
automatycznie usuwa białe znaki:
linecount=`wc -l < log.txt`
printf już przycina dla ciebie końcowy znak nowej linii:
$ printf '%s' $(wc -l < log.txt)
Szczegół:
%s
zastępczego łańcucha znaków. %s\n
), nie zrobi tego."$(command)"
. Wewnętrzne znaki nowej linii zostaną zachowane - i tylko nowa linia końcowa zostanie usunięta. Powłoka wykonuje tutaj całą pracę - printf
jest tylko sposobem na skierowanie wyników podstawiania poleceń z powrotem stdout
.
$( )
konstrukcją. Oto dowód:printf "%s" "$(perl -e 'print "\n"')"
$ printf '%s' "$(wc -l < log.txt)"
Jeśli chcesz usunąć tylko ostatnią nową linię , przeciągnij przez:
sed -z '$ s/\n$//'
sed
nie doda \0
końca do tego strumienia, jeśli ogranicznik jest ustawiony na NUL
via -z
, natomiast aby utworzyć plik tekstowy POSIX (zdefiniowany jako koniec a \n
), zawsze będzie wyświetlał końcowy \n
bez -z
.
Na przykład:
$ { echo foo; echo bar; } | sed -z '$ s/\n$//'; echo tender
foo
bartender
I aby udowodnić, że nie NUL
dodano:
$ { 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+$//'
sed
nie zapewnia -z
.
Jeśli chcesz wydrukować wynik czegokolwiek w Bash bez końca linii, echo to -n
przełącznikiem.
Jeśli masz go już w zmiennej, powtórz echo z przyciętym końcowym znakiem nowej linii :
$ testvar=$(wc -l < log.txt)
$ echo -n $testvar
Lub możesz to zrobić w jednym wierszu, zamiast tego:
$ echo -n $(wc -l < log.txt)
echo -n $(wc -l < log.txt)
ma ten sam efekt.