Mam ten kod w skrypcie powłoki:
sort input | uniq -c | sort -nr > output
Plik wejściowy nie zawierał wcześniejszych białych znaków, ale dane wyjściowe mają. Jak to naprawić? To jest bash
Mam ten kod w skrypcie powłoki:
sort input | uniq -c | sort -nr > output
Plik wejściowy nie zawierał wcześniejszych białych znaków, ale dane wyjściowe mają. Jak to naprawić? To jest bash
Odpowiedzi:
Domyślne zachowanie uniq polega na uzasadnieniu częstotliwości w linii o szerokości 7 spacji, a następnie oddzieleniu częstotliwości od elementu pojedynczą spacją.
Źródło: https://www.thelinuxrain.com/articles/tweaking-uniq-c
Usuń wiodące spacje za pomocą sed:
$ sort input | uniq -c | sort -nr | sed 's/^\s*//' > output
perl -pe 's/ *(\d+) /$1\t/'
( tutaj kilka alternatyw ). Ruruj do schowka, xclip -selection c
aby wkleić bezpośrednio do arkusza kalkulacyjnego.
FWIW możesz użyć innego narzędzia do sortowania dla większej elastyczności. Python jest jednym z takich narzędzi.
#!/usr/bin/python3
import sys, operator, collections
counter = collections.Counter(map(operator.methodcaller('rstrip', '\n'), sys.stdin))
for item, count in counter.most_common():
print(count, item)
Teoretycznie byłoby to nawet szybsze niż sort
narzędzie do dużych danych wejściowych, ponieważ powyższy program używa tabeli skrótów do identyfikacji duplikatów linii zamiast posortowanej listy. (Niestety, umieszcza wiersze o identycznej liczbie w arbitralnym, a nie naturalnym porządku; można to zmienić i nadal być szybsze niż dwie sort
inwokacje).
Jeśli chcesz więcej elastyczności na format wyjściowy można przyjrzeć się print()
i format()
wbudowanych funkcji.
Na przykład, jeśli chcesz wydrukować liczbę ósemkową z maksymalnie 7 zerami wiodącymi, a następnie znakiem tabulacji zamiast znaku spacji z zakończeniem linii NUL, zamień ostatni wiersz na:
print(format(count, '08o'), item, sep='\t', end='\0')
Zapisz skrypt w pliku, powiedzmy sort_count.py
, i wywołaj go za pomocą Pythona:
python3 sort_count.py < input
uniq -c -i | tr -s ' ' | cut -c 2-
Przetłumacz wiodące białe znaki na pojedyncze białe znaki za pomocą tr -s, a następnie wydrukuj wynik od drugiego znaku za pomocą cut -c.