Pobieranie pierwszych [x] znaków dla ciągu z potoku

58

Jeśli mam naprawdę długi wynik polecenia (pojedynczy wiersz), ale wiem, że chcę tylko pierwszych [x] (powiedzmy 8) znaków wyjścia, jaki jest najłatwiejszy sposób na uzyskanie tego? Nie ma żadnych ograniczników.

ksenoterracid
źródło
powiązane: stackoverflow.com/questions/1405611/…
Ciro Santilli 新疆 改造 中心 法轮功 六四 事件

Odpowiedzi:

82

Jednym ze sposobów jest użycie cut:

 command | cut -c1-8

To da ci pierwsze 8 znaków każdego wiersza wyniku. Ponieważ cutjest częścią POSIX, prawdopodobnie znajdzie się na większości Unices.

Steven D.
źródło
3
Zauważ, że cut -cwybiera znaki; cut -blub head -cwybiera bajty. To robi różnicę w niektórych lokalizacjach (w praktyce, gdy używasz UTF-8).
Gilles „SO- przestań być zły”
W tym przypadku nie musisz również określać indeksu początkowego. Powiedzenie cut -c-8wybierze postać od 1 do 8.
Sparhawk
@Steven, cutodpowiednikiem w systemie Windows jest?
Pacerier,
Również command | dd bs=8 count=1 2>/dev/null. Nie mówiąc, że jest krótszy lub lepszy. Po prostu kolejna alternatywa.
dubiousjim
@Gilles, ale należy pamiętać, że przy obecnych wersji GNU cut, cut -cdziała jak cut -b(to znaczy, że nie działa prawidłowo dla znaków wielo-bajtowych).
Stéphane Chazelas,
24

Są to inne sposoby na uzyskanie tylko pierwszych 8 znaków.

command | head -c8

command | awk '{print substr($0,1,8);exit}' 

command | sed 's/^\(........\).*/\1/;q'

A jeśli masz bash

var=$(command)
echo ${var:0:8}
użytkownik1606
źródło
2
Myślę, że następujący preparat sed jest nieco łatwiejsze do odczytania: command | sed 's/\(.\{8\}\).*/\1/'czy jeśli sed wspiera go: command | sed -r 's/(.{8}).*/\1/'; W przeciwnym razie +1
Steven D
Dobre rzeczy, ale pamiętaj, że head -cliczy się bajty , a nie znaki. Podobnie, wśród głównych implementacji Awk, tylko awk GNU obsługuje poprawnie znaki wielobajtowe - Awk FreeBSD i Mawk nie.
mklement0
2

Jeśli masz dostatecznie zaawansowaną powłokę (na przykład następujące polecenia będą działać w Bash, nie masz pewności co do myślnika), możesz:

read -n8 -d$'\0' -r <(command)

Po wykonaniu read ... <(command)twoje postacie będą w zmiennej powłoki REPLY. Wpisz, help readaby dowiedzieć się o innych opcjach.

Objaśnienie: -n8argument readmówi, że chcemy mieć do 8 znaków. -d$'\0'Mówi czytać aż null, zamiast do nowej linii. W ten sposób odczyt będzie kontynuowany przez 8 znaków, nawet jeśli jeden z wcześniejszych znaków jest znakiem nowej linii (ale nie, jeśli jest pusty). Alternatywą -n8 -d$'\0'jest użycie -N8, która odczytuje dokładnie 8 znaków lub dopóki standardowe wejście nie osiągnie EOF. Żaden ogranicznik nie jest honorowany. To prawdopodobnie lepiej pasuje do twoich potrzeb, ale nie wiem od razu, ile skorup ma odczyt, który honoruje, -Na nie honoruje -ni -d. Kontynuując wyjaśnienie: -rmówi ignoruj \-scapes, tak że na przykład traktujemy \\jak dwie postacie, a nie pojedyncze \.

Wreszcie robimy to read ... <(command)raczej niż command | read ...dlatego, że w drugiej formie odczyt jest wykonywany w podpowłoce, która jest następnie natychmiast zamykana, tracąc właśnie przeczytane informacje.

Inną opcją jest wykonanie całego przetwarzania w podpowłoce. Na przykład:

$ echo abcdefghijklm | { read -n8 -d$'\0' -r; printf "REPLY=<%s>\n" "$REPLY"; }
REPLY=<abcdefgh>
dubiousjim
źródło
1
Jeśli chcesz tylko wypisać 8 znaków i nie musisz przetwarzać ich w powłoce, po prostu użyj cut.
dubiousjim
Dobrze wiedzieć o read -n <num>; małe zastrzeżenie: Bash 3.x (wciąż obecny na OS) błędnie interpretuje <num>jako bajt liczby, a tym samym nie ze znaków wielo-bajtowych; zostało to naprawione w Bash 4.x.
mklement0
To świetna i przydatna odpowiedź. Znacznie bardziej ogólny niż inne.
not2qubit
2

Kolejne rozwiązanie liniowe z wykorzystaniem rozszerzenia parametrów

echo ${word:0:x}

EG: word="Hello world"
echo ${word:0:3} or echo ${word::3} 
o/p: Hel


EG.2: word="Hello world"
echo ${word:1:3}
o/p: ell
Prabhat Kumar Singh
źródło
Możesz także użyć zmiennej o długości, np .: x=8; echo ${word:0:$x}zamiast zakodować liczbę całkowitą.
Cometsong
1

To jest przenośne:

a="$(command)"             # Get the output of the command.
b="????"                   # as many ? as characters are needed.
echo ${a%"${a#${b}}"}      # select that many chars from $a

Zbudować ciąg znaków o zmiennej długości ma tutaj swoje własne pytanie .

Społeczność
źródło
0

Miałem ten problem podczas ręcznego generowania plików sum kontrolnych w repozytorium maven. Niestety cut -czawsze drukuje nowy wiersz na końcu wydruku. Aby stłumić to, którego używam xxd:

command | xxd -l$BYTES | xxd -r

Wyprowadza dokładnie $BYTESbajty, chyba że commandwynik jest krótszy, to dokładnie to wyjście.

Krzysztof Jabłoński
źródło
inną metodą zdejmowania cut| tr -d '\n'
ostatniej