Powiedzmy, że w ciągu dnia wielokrotnie napotykasz następującą formę skolumnizowanego wyniku jakiegoś polecenia w bash (w moim przypadku z wykonania svn st
w moim katalogu roboczym Railsów):
? changes.patch
M app/models/superman.rb
A app/models/superwoman.rb
aby pracować z wyjściem twojego polecenia - w tym przypadku z nazwami plików - wymagany jest jakiś rodzaj analizy, aby druga kolumna mogła być użyta jako dane wejściowe dla następnego polecenia.
To, co robiłem, to awk
dostać się do drugiej kolumny, np. Gdy chcę usunąć wszystkie pliki (nie to jest typowy przypadek użycia :), zrobiłbym:
svn st | awk '{print $2}' | xargs rm
Ponieważ często to piszę, naturalne pytanie brzmi: czy istnieje krótszy (a więc fajniejszy) sposób osiągnięcia tego w bashu?
UWAGA: To, o co pytam, jest zasadniczo pytaniem o polecenie powłoki, mimo że mój konkretny przykład dotyczy mojego przepływu pracy svn. Jeśli uważasz, że przepływ pracy jest głupi i zasugeruję alternatywne podejście, prawdopodobnie nie zagłosuję na ciebie, ale inni mogą, ponieważ pytanie tutaj naprawdę brzmi, jak uzyskać wynik polecenia n-tej kolumny w bash, w najkrótszy możliwy sposób . Dzięki :)
Odpowiedzi:
cut
Aby uzyskać dostęp do drugiego pola, możesz użyć :Edycja: Przepraszamy, nie zdawałem sobie sprawy, że SVN nie używa zakładek w swoich wynikach, więc jest to trochę bezużyteczne. Możesz dostosować
cut
dane wyjściowe, ale jest to trochę kruche - coś takiegocut -c 10-
mogłoby działać, ale dokładna wartość będzie zależeć od twojej konfiguracji.Inną opcją jest coś takiego:
sed 's/.\s\+//'
źródło
cut -f2
zsvn st
wyjściem. Zobaczysz, że to nie działa.svn st
użyje zakładek w swoim wyjściu. Po kilku testach wydaje się, że tak nie jest. Cholera.-d
to zadziałało.cut -d" " -f2
.Aby osiągnąć to samo, co:
używając tylko basha, możesz użyć:
To prawda, nie jest krótszy, ale jest nieco bardziej wydajny i poprawnie obsługuje białe znaki w nazwach plików.
źródło
a
ib
jak je zdobyć?a
reprezentuje pierwszą kolumnę ib
pozostałe kolumny. Jeśli chcesz wydrukować drugą kolumnę, użyj,read a b c;
a następnie użyjecho
zamiastrm
. Użyłem tego do uzyskania zestawu identyfikatorów zgodnych ze wzorcem grep, więc mogłem je wszystkie przerwać.Znalazłem się w tej samej sytuacji i ostatecznie dodałem te aliasy do mojego
.profile
pliku:Co pozwala mi pisać takie rzeczy:
źródło
function c() { awk "{print \$$1}" }
Wtedy możesz zrobić:svn st | c 2 | xargs rm
Wypróbuj zsh. Obsługuje alias przyrostków, więc możesz zdefiniować X w swoim .zshrc
wtedy możesz:
Możesz pójść o krok dalej i zdefiniować ją dla n-tej kolumny:
co zwróci n-tą kolumnę pliku "plik". Możesz to zrobić dla wyjścia grep lub mniejszego wyjścia. Jest to bardzo przydatne i zabójcze rozwiązanie zsh.
Możesz pójść o krok dalej i zdefiniować D jako:
Teraz możesz wpisać:
aby usunąć wszystkie pliki wymienione w pierwszej kolumnie pliku „plik”.
Jeśli znasz bash, zsh nie jest dużą zmianą, z wyjątkiem kilku nowych funkcji.
HTH Chris
źródło
cut
opcja. Po prostu nie działa na moim komputerze przy użyciu wyjściasvn st
. Spróbujsvn st | cut -d' ' -f2
tylko zobaczyć, co się stanie.Ponieważ wydaje się, że nie znasz skryptów, oto przykład.
Jeśli zapiszesz to
~/bin/x
i upewnisz się, że~/bin
jest w twoimPATH
(teraz to jest coś, co możesz i powinieneś umieścić w swoim.bashrc
), masz najkrótszą możliwą komendę do ogólnego wyodrębniania kolumny n; x n.Skrypt powinien poprawnie sprawdzić błędy i zwolnić, jeśli zostanie wywołany z argumentem nienumerycznym lub z nieprawidłową liczbą argumentów, itp. ale rozszerzenie tej podstawowej wersji podstawowej będzie w jednostce 102.
Może będziesz chciał rozszerzyć skrypt, aby zezwolić na inny ogranicznik kolumn. Awk domyślnie przetwarza dane wejściowe do pól na białych znakach; aby użyć innego separatora, użyj
-F ':'
gdzie:
jest nowym separatorem. Zaimplementowanie tego jako opcji do skryptu sprawia, że jest on nieco dłuższy, więc zostawiam to jako ćwiczenie dla czytelnika.Stosowanie
Biorąc pod uwagę plik
file
:Możesz przekazać go przez stdin (używając bezużytecznego
cat
jedynie jako symbolu zastępczego dla czegoś bardziej użytecznego);Lub podaj go jako argument do skryptu:
Tutaj
sh script.sh
zakłada się, że skrypt jest zapisywanyscript.sh
w aktualnym katalogu; jeśli zapiszesz go gdzieś w swoim miejscu pod bardziej użyteczną nazwąPATH
i oznaczysz jako wykonywalny, tak jak w instrukcjach powyżej, oczywiście użyj zamiast tego użytecznej nazwy (i niesh
).źródło
awk -v col=$col ...
cat
przykładu z powodów histerycznych (-:Wygląda na to, że masz już rozwiązanie. Aby było to łatwiejsze, dlaczego nie umieścić swojego polecenia w skrypcie basha (z krótką nazwą) i po prostu go uruchomić zamiast wpisywać to „długie” polecenie za każdym razem?
źródło
.bashrc
? Dlaczego miałbyś zaśmiecać go rzeczami niezwiązanymi z bash? Piszę osobne skrypty dla każdego „zestawu” poleceń i umieszczam je wszystkie w~/scripts
katalogu. Następnie dodaj całość~/scripts
do mojegoPATH
, abym mógł po prostu zadzwonić do nich po imieniu, kiedy ich potrzebuję.Jeśli nie przeszkadza Ci ręczne wybieranie kolumny, możesz bardzo szybko skorzystać z funkcji pick :
Po prostu przejdź do dowolnej komórki w drugiej kolumnie, naciśnij,
c
a następnie naciśnijenter
źródło
Zauważ, że ścieżka pliku nie musi znajdować się w drugiej kolumnie wyjścia svn st. Na przykład, jeśli zmodyfikujesz plik i zmodyfikujesz jego właściwość, będzie to trzecia kolumna.
Zobacz możliwe przykłady wyników w:
Przykładowe dane wyjściowe:
Proponuję wyciąć pierwsze 8 znaków przez:
Jeśli chcesz mieć 100% pewności i radzić sobie na przykład z wyszukanymi nazwami plików ze spacjami na końcu, musisz przeanalizować wyjście xml:
Oczywiście możesz chcieć użyć prawdziwego parsera XML zamiast grep / sed.
źródło