Mam kilka plików txt, chciałbym wypisać je małymi literami, tylko alfabetycznie i jedno słowo na wiersz, mogę to zrobić za pomocą kilku tr
poleceń w potoku:
tr -d '[:punct:]' <doyle_sherlock_holmes.txt | tr '[:upper:]' '[:lower:]' | tr ' ' '\n'
Czy można to zrobić w jednym skanie? Mógłbym napisać program w C, aby to zrobić, ale czuję, istnieje sposób, aby zrobić to za pomocą tr
, sed
, awk
lub perl
.
Odpowiedzi:
Możesz łączyć wiele tłumaczeń (oprócz złożonych przypadków obejmujących nakładające się zestawy zależne od ustawień regionalnych), ale nie możesz łączyć usuwania z tłumaczeniem.
Dwa połączenia
tr
będą prawdopodobnie szybsze niż pojedyncze połączenie z bardziej złożonymi narzędziami, ale jest to bardzo zależne od wielkości wejściowej, proporcji różnych znaków, implementacjitr
i konkurujących narzędzi, systemu operacyjnego, liczby rdzeni itp.źródło
tr -s '[:upper:] [:punct:]' '[:lower:]\n' <doyle_sherlock_holmes.txt
printf 'A.AAAA,A' | tr -s '[:upper:] [:punct:]' '[:lower:][\n*]'
dostajea\na\na'
, a transformacja dla... '[:lower:]\n'
może niekoniecznie w ogóle nic zrobić'[:punct:]'
- niektóretr
s obetną set1, aby dopasować 2, a niektóre wykonają domniemane[\n*]
. Lepiej po prostu użyć tam zasięgu.Oto kilka podejść:
GNU
grep
itr
: znajdź wszystkie słowa i umieść je małymi literamiGNU grep i perl: jak wyżej, ale perl obsługuje konwersję na małe litery
perl: znajdź wszystkie znaki alfabetyczne i wydrukuj je małymi literami (dzięki @steeldriver):
sed: usuwa wszystkie znaki, które nie są alfabetyczne ani spacje, zastępuje wszystkie znaki alfabetyczne ich małymi wersjami i zastępuje wszystkie spacje nowymi liniami. Zauważ, że zakłada to, że wszystkie białe znaki to spacje, bez tabulatorów.
źródło
perl -lne 'print lc for /[[:alpha:]]+/g'
też zadziała? czy jest to kiepski styl? (Jestem nowy w Perlu i próbuję się uczyć!)sed -z 's/\W*\(\w\+\)\W*/\L\1\n/g'
sed
można\w
teraz zrobić ? Fajne!sed
--z
zmienia on cyklicznie na\0NUL
s, a nie na nowe linie. Całkiem fajne, gdy robisz coś takiegotar -c . | tr -s \\0 | sed -z ...
- ale trochę powolne.Tak. Możesz to zrobić w /
tr
w ustawieniach ASCII (co w przypadku GNU jesttr
swego rodzaju jedyną funkcją) . Możesz użyć klas POSIX lub możesz odwoływać się do wartości bajtów każdego znaku według liczby ósemkowej. Możesz także podzielić ich transformacje na zakresy.Powyższe polecenie przekształciłoby wszystkie wielkie litery na małe, całkowicie zignorowało wielkie litery i przekształciło wszystkie inne znaki na nowe znaki. Oczywiście wtedy kończysz z mnóstwem pustych linii. Do
tr
-s
powtórzenia queeze przełączania mogą być przydatne w tej sprawie, ale jeśli używasz go u boku[:upper:]
do[:lower:]
transformacji wtedy można skończyć ściskając duże litery, jak również. W ten sposób nadal wymaga drugiego filtra, takiego jak ......lub...
... a więc jest o wiele mniej wygodne niż robienie ...
... który ściska
-c
dopełnienie znaków alfabetycznych sekwencją w jeden nowy wiersz, a następnie przekształca górne na dolne po drugiej stronie rury.Nie oznacza to, że zakresy tego rodzaju nie są przydatne. Rzeczy jak:
... może być bardzo przydatny, ponieważ konwertuje bajty wejściowe na wszystkie cyfry w rozproszonym spektrum ich wartości. Nie marnuj, nie chcesz, wiesz.
Może to obejmować inny sposób przeprowadzenia transformacji
dd
.Ponieważ
dd
może to zrobić zarównounblock
ilcase
konwersji w tym samym czasie, może to być nawet możliwe, aby przejść dużo pracy poza nim. Ale to może być naprawdę użyteczne tylko wtedy, gdy możesz dokładnie przewidzieć liczbę bajtów na słowo - lub przynajmniej można wcześniej wstawić każde słowo spacjami do przewidywalnej liczby bajtów, ponieważunblock
je końcowe spacje na końcu każdego bloku.źródło
dd
zaangażowanie :)