Mam ciąg:
one_two_three_four_five
Muszę zapisać w A
wartości zmiennej two
i B
wartości zmiennej four
z powyższego ciągu
Użyj cut
z _
jako separatora pól i uzyskaj żądane pola:
A="$(cut -d'_' -f2 <<<'one_two_three_four_five')"
B="$(cut -d'_' -f4 <<<'one_two_three_four_five')"
Możesz także użyć echo
i potoku zamiast ciągu Tutaj:
A="$(echo 'one_two_three_four_five' | cut -d'_' -f2)"
B="$(echo 'one_two_three_four_five' | cut -d'_' -f4)"
Przykład:
$ s='one_two_three_four_five'
$ A="$(cut -d'_' -f2 <<<"$s")"
$ echo "$A"
two
$ B="$(cut -d'_' -f4 <<<"$s")"
$ echo "$B"
four
$ echo $FILE
my_user/my_folder/file.csv
$ A="$(cut -d'/' -f2 <<<"$FILE")"
$ echo $A
[file]*
Czy wiesz, co się tutaj dzieje?echo "${s##*_}"
Używając tylko konstruktorów sh POSIX, możesz używać konstrukcji podstawiania parametrów do parsowania jednego separatora na raz. Zauważ, że ten kod zakłada, że istnieje wymagana liczba pól, w przeciwnym razie ostatnie pole zostanie powtórzone.
Alternatywnie, możesz użyć niecytowanego podstawienia parametru z wyłączonym rozszerzaniem symboli wieloznacznych i
IFS
ustawionym na znak separatora (działa to tylko wtedy, gdy separator jest pojedynczym znakiem spacji lub dowolna sekwencja białych znaków jest separatorem).Spowoduje to zablokowanie parametrów pozycji. Jeśli zrobisz to w funkcji, wpływa to tylko na parametry pozycyjne funkcji.
Jeszcze innym podejściem jest użycie
read
wbudowanego.źródło
unset IFS
nie powracaIFS
do wartości domyślnych. Jeśli później ktoś to zrobi,OldIFS="$IFS"
będzie miał wartość zerową w OldIFS. Zakłada się również, że poprzednia wartość IFS jest wartością domyślną, co jest bardzo możliwe (i przydatne), że nie będzie. Jedynym prawidłowym rozwiązaniem jest przechowywanie,old="$IFS"
a później przywracanie z IFS = „$ old”. Lub ... użyj podpowłoki(...)
. Albo jeszcze lepiej przeczytaj moją odpowiedź.unset IFS
nie przywracaIFS
wartości domyślnej, ale przywraca podział pola do domyślnego efektu. Tak, jest to ograniczenie, ale w praktyce jest zwykle dopuszczalne. Problem z podpowłoką polega na tym, że musimy wyciągnąć z niej dane. Pokazuję rozwiązanie, które nie zmienia stanu na końcuread
. (Działa w powłokach POSIX, ale IIRC nie w powłoce Bourne'a, ponieważ działałbyread
w podpowłoce z powodu dokumentu tutaj.) Użycie<<<
odpowiedzi w tobie jest wariantem, który działa tylko w ksh / bash / zsh.user/my_folder/[this_is_my_file]*
? Po tych krokach otrzymuję[this_is_my_file]*
/
.Chciałem zobaczyć
awk
odpowiedź, więc oto jedna:źródło
awk -F_ '{print $NF}' <<< 'one_two_3_4_five'
Najprostszym sposobem (dla muszli z <<<) jest:
Używanie zmiennej czasowej
$a
zamiast$_
ponieważ jedna powłoka narzeka.W pełnym skrypcie:
Bez zmian IFS, nie ma problemów z
set -f
(rozwinięcie nazwy ścieżki) Brak zmian parametrów pozycyjnych („$ @”).W przypadku rozwiązania przenośnego dla wszystkich powłok (tak, wszystkie POSIX włącznie) bez zmiany IFS lub
set -f
użyj (nieco bardziej złożonego) odpowiednika heredoc:Zrozum, że te rozwiązania (zarówno tutaj-doc, jak i użycie
<<<
usunie wszystkie końcowe znaki nowej linii.I że jest to zaprojektowane dla zmiennej zawartości „jednej linii”.
Rozwiązania dla wielu linii są możliwe, ale wymagają bardziej złożonych konstrukcji.
Bardzo proste rozwiązanie jest możliwe w wersji bash 4.4
Nie ma odpowiednika dla powłok POSIX, ponieważ wiele powłok POSIX nie ma tablic.
W przypadku powłok posiadających tablice mogą być tak proste, jak:
(testowane w attsh, lksh, mksh, ksh i bash)
Ale z dużą ilością dodatkowej instalacji hydraulicznej, aby zachować i zresetować zmienne i opcje:
W Zsh tablice zaczynają się od 1 i domyślnie nie dzielą łańcucha.
Tak więc należy wprowadzić pewne zmiany, aby działało to w Zsh.
źródło
read
są proste, o ile OP nie chce wyodrębnić 76. i 127. elementu z długiego łańcucha ...readarray
w tej sytuacji może być łatwiejszy w użyciu.Dzięki
zsh
możesz podzielić ciąg (on_
) na tablicę:a następnie uzyskać dostęp do każdego elementu za pomocą indeksu tablicy:
Należy pamiętać, że w
zsh
(w przeciwieństwie doksh
/bash
) indeksy tablicowe zaczynają się od 1 .źródło
set -f
ostrzeżenie do pierwszego rozwiązania. ...*
może gwiazdki ?set -f
? Nie używamread
/IFS
. Wypróbuj moje rozwiązania z ciągiem podobnym*_*_*
lub czymkolwiek ...Czy rozwiązanie python jest dozwolone?
źródło
Kolejny przykład awk; prostsze do zrozumienia.
Może być również używany ze zmiennymi.
Załóżmy, że:
this_str = "one_two_three_four_five"
Następnie działają następujące elementy:
A = `echo $ {this_str} | awk -F_ '{print $ 1}' '
B = `echo $ {this_str} | awk -F_ '{print $ 2}' '
C = `echo $ {this_str} | awk -F_ '{print $ 3}' '
... i tak dalej ...
źródło