Użyj spacji jako separatora z poleceniem cut


328

Chcę użyć spacji jako separatora z cutpoleceniem.

Jakiej składni mogę do tego użyć?


42
nieprawda, strona podręcznika do cięcia nie wyjaśnia tego i ogólnie nie ma charakteru informacyjnego
UncleZeiv,

2
Również „cięcie informacji” nie poprawia się w tym przypadku.
mężczyzna z Cardiff

3
@ mklement0, o ile pamiętam, odpowiadałem na komentarz, który został usunięty, który odrzucał odpowiedź na to pytanie jako odpowiedź na stronie podręcznika, która moim zdaniem była „nieprawdziwa”, niezależnie od tego, że jest to uzasadniony powód czy nie - teraz, chociaż przyznaję, że może istnieć dobry powód tego braku informacji, nadal uważam, że dokumentacja bez typowych przykładów użycia jest często co najmniej irytująca, a nawet wręcz bezużyteczna
UncleZeiv

3
@UncleZeiv Rozumiem; dzięki za wytłumaczenie; biorąc pod uwagę zainteresowanie tym pytaniem, można założyć, że manstrona nie wystarczy. Spójrzmy: „ -d delimUżyj delimjako znaku separatora pola zamiast znaku tabulacji”. (BSD cut, ale wersja GNU i specyfikacja POSIX są prawie takie same). Używanie powłoki do wywoływania cut- typowy przypadek - wymaga zatem, abyś na ogół przekazywał spację jako argument przy użyciu składni powłoki , co prawdopodobnie nie cutjest zadaniem strony man. Przykłady ze świata rzeczywistego zawsze jednak pomagają, a strona podręcznika GNU nie ma ich.
mklement0

4
chociaż wybrana odpowiedź jest prawidłowa pod względem technicznym, rozważ wybranie najnowszej i wyczerpującej odpowiedzi @ mklement0 jako odpowiedzi kanonicznej, aby filtrowała się na górę.
David LeBauer,

Odpowiedzi:


367
cut -d ' ' -f 2

Gdzie 2 to numer pola rozdzielanego spacjami pola, które chcesz.


2
czy możesz powiedzieć cutowi, aby używał dowolnej liczby określonego znaku jako separatora, jak w RegEx? np. dowolna liczba spacji, np. \ s +
amfibia

3
@foampile Nie, nie wierzę, że możesz.
Jonathan Hartley,

6
Nie możesz używać wyrażeńcutcutscut
regularnych

czy możesz dostać co trzecie pole rozdzielane spacjami? lubisz cut -d ' ' -f 3,6,9,12,15,18bez konieczności podawania każdej liczby?
Monocito

169

Zwykle, jeśli używasz spacji jako separatora, chcesz traktować wiele spacji jako jedną, ponieważ analizujesz wynik polecenia wyrównującego niektóre kolumny ze spacjami. (a wyszukiwanie google prowadzi mnie tutaj)

W takim przypadku jedno cutpolecenie nie jest wystarczające i musisz użyć:

tr -s ' ' | cut -d ' ' -f 2

Lub

awk '{print $2}'

2
Dzięki za użycie przykładowego awk, właśnie tego potrzebowałem.
spazm

44

Uzupełnienie istniejących, pomocnych odpowiedzi; czapka dla wsparcia QZ za zachęcenie mnie do opublikowania osobnej odpowiedzi:

W grę wchodzą dwa różne mechanizmy :

  • (a) czy cut sam wymaga separatora (w tym przypadku spacji) przekazanego do -dopcji jako osobnego argumentu, czy też dopuszczalne jest bezpośrednie dołączenie go do opcji -d.

  • (b) w jaki sposób powłoka na ogół analizuje argumenty przed przekazaniem ich do wywoływanego polecenia.

(a) odpowiada cytat z wytycznych POSIX dla narzędzi (wyróżnienie moje)

Jeżeli SYNOPSIS standardowego narzędzia pokazuje opcję z obowiązkowym argumentem opcji [...], aplikacja zgodna zastosuje osobne argumenty dla tej opcji i jej argumentu opcji . Jednak zgodna implementacja umożliwia również aplikacjom określenie opcji i argumentu opcji w tym samym ciągu argumentu bez ingerencji w znaki .

Innymi słowy: W tym przypadku, ponieważ -dargument-opcji jest obowiązkowy , możesz wybrać, czy określić separator jako :

  • (s) EITHER: osobny argument
  • (d) LUB: jako wartość bezpośrednio związana z-d .

Po wybraniu (S) lub (D), to skorupa Stringi-dosłowny parsowania - (B) - który sprawach:

  • Przy podejściu (-ach) wszystkie poniższe formularze są RÓWNOWAŻNE:

    • -d ' '
    • -d " "
    • -d \<space> # <space> used to represent an actual space for technical reasons
  • Zgodnie z podejściem (d) wszystkie poniższe formularze są RÓWNOWAŻNE:

    • -d' '
    • -d" "
    • "-d "
    • '-d '
    • d\<space>

Równoważność tłumaczy się powłoki „przetwarzający łańcuchach dosłownym:

Wszystkie powyższe rozwiązania dają dokładnie ten sam ciąg (w każdej grupie) do czasu, gdy cutje zobaczy :

  • (s) : cutwidzi -djako swój własny argument, po którym następuje osobny argument zawierający znak spacji - bez cudzysłowów i \prefiksu !.

  • (d) : cutwidzi -d plus znak spacji - bez cudzysłowów i \prefiksów! - jako część tego samego argumentu.

Powód, dla którego formy w odpowiednich grupach są ostatecznie identyczne, jest dwojaki, w zależności od tego, jak powłoka analizuje literały łańcuchowe :

  • Powłoka umożliwia dosłownym być określone jak przez mechanizm zwany cytowanie , które mogą przyjmować różne formy :
    • ciągi pojedynczego cudzysłowu : zawartość '...'jest traktowana dosłownie i tworzy pojedynczy argument
    • łańcuchy cudzysłowów : zawartość wewnątrz "..."również tworzy pojedynczy argument, ale podlega interpolacji (rozszerza odniesienia do zmiennych, takie jak $varpodstawienia poleceń ( $(...)lub `...`) lub rozszerzenia arytmetyczne ( $(( ... ))).
    • \- cytowanie pojedynczych znaków : \poprzedzenie pojedynczego znaku powoduje, że znak ten jest interpretowany jako dosłowny.
  • Cytowanie jest uzupełniony przez usuwanie cytowań , co oznacza, że gdy powłoka jest analizowana wiersz polecenia, to usuwa znaki cytat z argumentów (załączając '...'lub "..."lub \wystąpienia) - w ten sposób istota komenda wywołana nigdy nie widzi znaki cudzysłowu .

36

Możesz też powiedzieć:

cut -d\  -f 2

Zauważ, że po odwrotnym ukośniku są dwie spacje.


30
Osoba, która wie, że „\” ucieka przed następną postacią, bardzo ostrożnie zauważyłaby, co będzie dalej. Używanie „\” do ucieczki takich znaków spacji jest bardzo powszechnym idiomem.
Jonathan Hartley

3
@Jonathan Hartley zwykle większość kodów jest rzeczywiście nieczytelna :)
Luca Borrione

1
Z perspektywy linux / unix \ była to moja pierwsza próba i zadziałała. Zgadzam się, że jest to mniej oczywiste w porównaniu do ' ', ale jestem pewien, że wielu chętnie czyta to tutaj jako potwierdzenie zachowania. Aby lepiej zrozumieć, zobacz komentarz @ mklement0 poniżej.
tresf

@ Korekta Jonathana Hartleya: „ samolubna osoba, która wie, że„ \ ”ucieka przed następną postacią i zakłada, że wszyscy inni też to wiedzą”. W przypadku projektów osobistych nie ma to zastosowania, ale w zespołach założenie to jest bardzo niebezpieczne (i potencjalnie kosztowne).
Eduard Nicodei,

1
@EduardNicodei Oh zgadzam się. Rozmawialiśmy o czytelnikach kodu („kto zauważa ...?”), A nie autorach. Ale także w niektórych zespołach dobrze jest założyć pewien poziom biegłości. Zależy od środowiska.
Jonathan Hartley,

5

I właśnie odkrył , że można również użyć "-d ":

cut "-d "

Test

$ cat a
hello how are you
I am fine
$ cut "-d " -f2 a
how
am

1
Rzeczywiście - lub '-d '.
mklement0

3
Należy zauważyć, że z cut„s perspektywy wszystkich poniższych są identyczne: "-d ", '-d ', -d" ", -d' ', i -d\<space>: wszystkie formy bezpośrednio dołączyć argumentów opcji (spacja) do wyboru ( -d), a wynik w dokładnie taki sam ciąg do czasu cutwidzi je: pojedynczy argument zawierający D, a następnie przez przestrzeń po powłoka występowała usuwanie cytat
mklement0

1
@ odpowiedź mklement0 powinna być odpowiedź. Jest to najbardziej wszechstronny na tej stronie (nawet jeśli jest to komentarz).
tresf

@QZSupport: Doceniam sentyment i zachętę - zainspirowało mnie to do opublikowania własnej odpowiedzi z dodatkowymi informacjami dodatkowymi.
mklement0

1
Lol fascynujące odkrycie!
Harry,

4

Nie można tego łatwo zrobić z wycięciem, jeśli dane zawierają na przykład wiele spacji. Uważam, że użyteczne jest znormalizowanie danych wejściowych w celu łatwiejszego przetwarzania. Jedną sztuczką jest użycie sed do normalizacji, jak poniżej.

echo -e "foor\t \t bar" | sed 's:\s\+:\t:g' | cut -f2  #bar

3

scut , narzędzie przypominające cięcie (mądrzejsze, ale wolniejsze, które stworzyłem), które może używać dowolnego wyrażenia regularnego perla jako token łamania. Łamanie na białych znakach jest domyślne, ale możesz także łamać wyrażenia regularne zawierające wiele znaków, alternatywne wyrażenia regularne itp.

scut -f='6 2 8 7' < input.file  > output.file

więc powyższe polecenie podzieli kolumny na białe spacje i wyodrębni (6 0) kolumny 6 2 8 7 w tej kolejności.


0

Mam odpowiedź (przyznaję nieco mylącą odpowiedź), która obejmuje sedwyrażenia regularne i grupy przechwytywania:

  • \S* - pierwsze słowo
  • \s* - separator
  • (\S*) - drugie słowo - zrobione
  • .* - reszta linii

Jako sedekspresji, potrzeby grupy przechwytywania być uciekł, IE \(i \).

W \1Zwraca kopię przechwyconego grupy, czyli drugie słowo.

$ echo "alpha beta gamma delta" | sed 's/\S*\s*\(\S*\).*/\1/'
beta

Kiedy spojrzysz na tę odpowiedź, jest to nieco mylące i, możesz pomyśleć, po co zawracać sobie głowę? Mam nadzieję, że niektórzy mogą powiedzieć „Aha!” i użyje tego wzorca, aby rozwiązać niektóre skomplikowane problemy z wyodrębnianiem tekstu za pomocą jednego sedwyrażenia.

Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.