Załóżmy, że mam ciąg znaków 1:2:3:4:5
i chcę uzyskać jego ostatnie pole ( 5
w tym przypadku). Jak to zrobić za pomocą Bash? Próbowałem cut
, ale nie wiem, jak określić ostatnie pole -f
.
293
Możesz użyć operatorów łańcuchowych :
$ foo=1:2:3:4:5
$ echo ${foo##*:}
5
To łapczywie przycina wszystko od przodu do „:”.
${foo <-- from variable foo
## <-- greedy front trim
* <-- matches anything
: <-- until the last ':'
}
5
jeśli ciąg jest1:2:3:4:5:
(podczas korzystania z operatorów ciąg daje pusty wynik). Jest to szczególnie przydatne podczas analizowania ścieżek, które mogą zawierać (lub nie) postać końcową/
.${foo%:*}
.#
- od początku;%
- od końca.#
,%
- najkrótszy mecz;##
,%%
- najdłuższy mecz.echo ${pwd##*/}
nie działa.pwd
jako zmienną. Spróbowaćdir=$(pwd); echo ${dir##*/}
. Pracuje dla mnie!Innym sposobem jest odwrócenie przed i po
cut
:Ułatwia to uzyskanie przedostatniego pola lub dowolnego zakresu pól ponumerowanych od końca.
źródło
echo "1 2 3 4" | rev | cut -d " " -f1 | rev
rev
, właśnie tego potrzebowałem!cut -b20- | rev | cut -b10- | rev
Trudno jest uzyskać ostatnie pole za pomocą cut, ale oto kilka rozwiązań w awk i perl
źródło
/
znak końcowy lub nie :/a/b/c/d
i/a/b/c/d/
daje ten sam wynik (d
) podczas przetwarzaniapwd | awk -F/ '{print $NF}'
. Przyjęta odpowiedź powoduje, że wynik jest pusty w przypadku/a/b/c/d/
/
jako separatora, a jeśli twoja ścieżka jest/my/path/dir/
, użyje wartości po ostatnim separatorze, który jest po prostu pustym ciągiem. Więc najlepiej unikać końcowego slashowania, jeśli musisz zrobić coś takiego jak ja.awk '{$NF=""; print $0}' FS=: OFS=:
często działa wystarczająco dobrze.Zakładając dość proste użycie (na przykład bez ucieczki z separatora), możesz użyć grep:
Podział - znajdź wszystkie znaki nie ogranicznik ([^:]) na końcu wiersza ($). -o drukuje tylko pasującą część.
źródło
Jednokierunkowa:
Inny, używając tablicy:
Jeszcze inny z tablicą:
Używanie wyrażeń regularnych Bash (wersja> = 3.2):
źródło
Po prostu przetłumacz ogranicznik na nowy wiersz i wybierz ostatni wpis za pomocą
tail -1
.źródło
\n
, ale w większości przypadków jest to najbardziej czytelne rozwiązanie.Używanie
sed
:źródło
Jeśli twoje ostatnie pole to pojedynczy znak, możesz to zrobić:
Sprawdź manipulację ciągiem w bash .
źródło
a
, nie ostatni pola .Tutaj jest wiele dobrych odpowiedzi, ale nadal chcę udostępnić tę za pomocą basename :
Jednak nie powiedzie się, jeśli w ciągu jest już trochę „/” . Jeśli slash / jest twoim ogranicznikiem, musisz (i powinieneś) użyć basename.
To nie jest najlepsza odpowiedź, ale pokazuje tylko, jak możesz być kreatywny za pomocą poleceń bash.
źródło
Korzystanie z Bash.
źródło
echo ${!#}
zamiasteval echo \$${#}
.Najpierw użyj xargs, podziel go za pomocą „:”, - n1 oznacza, że każda linia ma tylko jedną część.
źródło
źródło
Dla tych, którzy dobrze znają Python, https://github.com/Russell91/pythonpy to dobry wybór, aby rozwiązać ten problem.
Z pomocą pythonpy:
-x treat each row of stdin as x
.Za pomocą tego narzędzia łatwo jest napisać kod Pythona, który zostanie zastosowany do danych wejściowych.
źródło
Odpowiedź może być nieco spóźniona, chociaż prostym rozwiązaniem jest odwrócenie kolejności ciągu wejściowego. To pozwoli ci zawsze zdobyć ostatni przedmiot bez względu na długość.
Należy jednak pamiętać, że jeśli używasz tej metody, a liczby są większe niż 1 cyfra (lub w każdym przypadku większe niż jeden znak), będziesz musiał uruchomić inną komendę „rev” na wyjściu potokowym.
Mam nadzieję, że mogę pomóc, na zdrowie
źródło
Rozwiązanie wykorzystujące wbudowane czytanie:
Lub, aby uczynić go bardziej ogólnym:
źródło
Jeśli podoba Ci się Python i masz opcję instalacji pakietu, możesz użyć tego narzędzia Python .
źródło
echo "1:2:3:4:5" | python -c "import sys; print(list(sys.stdin)[0].split(':')[-1])"
pythonp
pakietu jest zrobienie tego samego, copython -c
przy mniejszej liczbie znaków. Proszę spojrzeć na README w repozytorium.Dopasowywanie wyrażeń regularnych
sed
jest zachłanne (zawsze przechodzi do ostatniego wystąpienia), co możesz wykorzystać na swoją korzyść tutaj:źródło