Jak podzielić ciąg znaków na separatorze w Bash?
Mam ten ciąg przechowywany w zmiennej:
IN="[email protected];[email protected]"
Teraz chciałbym podzielić ciągi przez ;
ogranicznik tak, że mam:
ADDR1="[email protected]"
ADDR2="[email protected]"
Niekoniecznie potrzebuję zmiennych ADDR1
i ADDR2
. Jeśli są elementami tablicy, to nawet lepiej.
Po sugestiach z Odpowiedzi poniżej, skończyło się na tym, co było po:
#!/usr/bin/env bash
IN="[email protected];[email protected]"
mails=$(echo $IN | tr ";" "\n")
for addr in $mails
do
echo "> [$addr]"
done
Wyjście:
> [[email protected]]
> [[email protected]]
Było rozwiązanie polegające na ustawieniu Internal_field_separator (IFS) to ;
. Nie jestem pewien co się stało z tą odpowiedzią, jak zresetować IFS
z powrotem do domyślnego?
RE: IFS
Rozwiązanie, próbowałem tego i działa, zachowuję Stary IFS
a potem go przywracam:
IN="[email protected];[email protected]"
OIFS=$IFS
IFS=';'
mails2=$IN
for x in $mails2
do
echo "> [$x]"
done
IFS=$OIFS
BTW, kiedy próbowałem
mails2=($IN)
Otrzymałem tylko pierwszy ciąg podczas drukowania go w pętli, bez nawiasów wokół {[13] } Działa.
30 answers
Możesz ustawić zmienną wewnętrzny separator pól (IFS), a następnie pozwolić jej przetworzyć do tablicy. Jeśli tak się dzieje w poleceniu, wtedy przypisanie do IFS
ma miejsce tylko w środowisku tego pojedynczego polecenia (do read
). Następnie przetwarza dane wejściowe zgodnie z wartością zmiennej IFS
do tablicy, którą możemy następnie iterować.
IFS=';' read -ra ADDR <<< "$IN"
for i in "${ADDR[@]}"; do
# process "$i"
done
Przetworzy jeden wiersz elementów oddzielonych ;
, wpychając go do tablicy. Rzeczy do przetworzenia całości $IN
, za każdym razem jeden Linia wejścia oddzielona przez ;
:
while IFS=';' read -ra ADDR; do
for i in "${ADDR[@]}"; do
# process "$i"
done
done <<< "$IN"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-03-08 20:31:44
Wzięte z Bash shell script split array:
IN="[email protected];[email protected]"
arrIN=(${IN//;/ })
Wyjaśnienie:
Ta konstrukcja zastępuje wszystkie wystąpienia ';'
(początkowe //
oznacza globalne zastąpienie) w łańcuchu IN
na ' '
(pojedyncza spacja), a następnie interpretuje łańcuch rozdzielony spacjami jako tablicę (tak robią otaczające nawiasy).
Składnia używana wewnątrz nawiasów klamrowych do zastąpienia każdego znaku {[1] } znakiem ' '
nazywa się parametrem Rozszerzenie .
Istnieją pewne wspólne gotchas:
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-04-13 12:36:28
Jeśli nie masz nic przeciwko przetworzeniu ich natychmiast, Lubię to zrobić:
for i in $(echo $IN | tr ";" "\n")
do
# process
done
Możesz użyć tego rodzaju pętli do zainicjowania tablicy, ale prawdopodobnie jest na to łatwiejszy sposób. Mam nadzieję, że to pomoże.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-28 02:09:44
Zgodna odpowiedź
Do tego pytania, istnieje już wiele różnych sposobów, aby to zrobić w bash. Ale bash ma wiele specjalnych funkcji, tak zwanych bashism to działa dobrze, ale to nie zadziała w żadnej innej powłoce.
W szczególności tablice, asocjacyjna tablica i podstawienie wzorca są czystymi i mogą nie działać pod innymi muszle .
Na moim Debianie GNU / Linux , Istnieje standardowa powłokao nazwie dash, ale znam wielu ludzi, którzy lubią używać ksh.
Wreszcie, w bardzo małej sytuacji, istnieje specjalne narzędzie o nazwie busybox z własnym interpreterem powłoki ( ash ).
Requested string
Próbka ciągu w tak pytaniu to:
IN="[email protected];[email protected]"
Ponieważ może to być przydatne z spacjami i jako spacje mogą zmodyfikować wynik procedury, wolę użyć tego przykładowego ciągu znaków:
IN="[email protected];[email protected];Full Name <[email protected]>"
Podziel ciąg znaków na podstawie ogranicznika w bash (Wersja >=4.2)
Pod pure bash, możemy używać tablic I IFS :
var="[email protected];[email protected];Full Name <[email protected]>"
oIFS="$IFS"
IFS=";"
declare -a fields=($var)
IFS="$oIFS"
unset oIFS
IFS=\; read -a fields <<<"$var"
Używanie tej składni pod ostatnim bashem nie zmienia $IFS
dla bieżącej sesji, ale tylko dla bieżącego polecenia:
set | grep ^IFS=
IFS=$' \t\n'
Teraz string var
jest dzielony i przechowywany w tablicy (o nazwie fields
):
set | grep ^fields=\\\|^var=
fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
var='[email protected];[email protected];Full Name <[email protected]>'
Możemy poprosić o zawartość zmiennej za pomocą declare -p
:
declare -p var fields
declare -- var="[email protected];[email protected];Full Name <[email protected]>"
declare -a fields=([0]="[email protected]" [1]="[email protected]" [2]="Full Name <[email protected]>")
read
jest najszybszy sposób na podział, ponieważ nie ma widełek i żadnych zewnętrznych zasobów wywołanych.
Stamtąd możesz użyć składni, którą już znasz do przetwarzania każdego pola:
for x in "${fields[@]}";do
echo "> [$x]"
done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]
Lub upuść każde pole po przetworzeniu (Lubię to przesunięcie "podejście": {]}
while [ "$fields" ] ;do
echo "> [$fields]"
fields=("${fields[@]:1}")
done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]
Lub nawet dla prostego wydruku (krótsza składnia):
printf "> [%s]\n" "${fields[@]}"
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]
Podziel ciąg znaków na podstawie ogranicznika w powłoce
Ale jeśli chcesz napisać coś użytecznego pod wieloma powłokami, musisz , a nie używaćbashisms .
Istnieje składnia, używana w wielu powłokach, do dzielenia ciągu znaków na first lub last występowanie podłańcucha:
${var#*SubStr} # will drop begin of string up to first occur of `SubStr`
${var##*SubStr} # will drop begin of string up to last occur of `SubStr`
${var%SubStr*} # will drop part of string from last occur of `SubStr` to the end
${var%%SubStr*} # will drop part of string from first occur of `SubStr` to the end
(brak tego jest głównym powodem mojego Publikacja odpowiedzi;)
Jak wskazuje Score_Under:
#
i%
Usuń najkrótszy możliwy pasujący ciąg znaków, i
##
i%%
usuń jak najdłużej.
Ten mały przykładowy skrypt działa dobrze pod bash, dash, ksh, busybox i był testowany również pod Mac-OS bash:
var="[email protected];[email protected];Full Name <[email protected]>"
while [ "$var" ] ;do
iter=${var%%;*}
echo "> [$iter]"
[ "$var" = "$iter" ] && \
var='' || \
var="${var#*;}"
done
> [[email protected]]
> [[email protected]]
> [Full Name <[email protected]>]
Baw się dobrze!Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-23 17:37:51
Widziałem kilka odpowiedzi odwołujących się do komendy cut
, ale wszystkie zostały usunięte. To trochę dziwne, że nikt nie rozwinął się na ten temat, ponieważ myślę, że jest to jedna z bardziej przydatnych komend do robienia tego typu rzeczy, szczególnie do parsowania rozdzielonych plików dziennika.
W przypadku podziału tego konkretnego przykładu na tablicę skryptów bash, tr
jest prawdopodobnie bardziej wydajny, ale cut
może być użyty i jest bardziej efektywny, jeśli chcesz wyciągnąć określone pola z środek.
Przykład:
$ echo "[email protected];[email protected]" | cut -d ";" -f 1
[email protected]
$ echo "[email protected];[email protected]" | cut -d ";" -f 2
[email protected]
Można oczywiście umieścić to w pętli i iterację parametru-f, aby wyciągnąć każde pole niezależnie.
Staje się to bardziej przydatne, gdy masz rozdzielony plik dziennika z wierszami takimi jak:
2015-04-27|12345|some action|an attribute|meta data
cut
jest bardzo przydatne, aby móc cat
ten plik i wybrać konkretne pole do dalszego przetwarzania.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-28 22:17:52
Jak o tym podejściu:
IN="[email protected];[email protected]"
set -- "$IN"
IFS=";"; declare -a Array=($*)
echo "${Array[@]}"
echo "${Array[0]}"
echo "${Array[1]}"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-07-20 16:21:05
To mi pomogło:
string="1;2"
echo $string | cut -d';' -f1 # output is 1
echo $string | cut -d';' -f2 # output is 2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-24 02:33:53
echo "[email protected];[email protected]" | sed -e 's/;/\n/g'
[email protected]
[email protected]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-05-28 02:12:59
To również działa:
IN="[email protected];[email protected]"
echo ADD1=`echo $IN | cut -d \; -f 1`
echo ADD2=`echo $IN | cut -d \; -f 2`
Bądź ostrożny, to rozwiązanie nie zawsze jest poprawne. W przypadku, gdy zdasz "[email protected]" tylko, przypisze go zarówno do ADD1, jak i ADD2.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-17 01:39:20
Myślę, że AWK jest najlepszym i skutecznym poleceniem do rozwiązania Twojego problemu. AWK jest domyślnie dołączany do Bash w prawie każdej dystrybucji Linuksa.
echo "[email protected];[email protected]" | awk -F';' '{print $1,$2}'
Da
[email protected] [email protected]
Oczywiście można zapisać każdy adres e-mail poprzez ponowne zdefiniowanie pola drukowania awk.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-19 22:26:52
Inne spojrzenie naodpowiedź Darrona, tak to robię:
IN="[email protected];[email protected]"
read ADDR1 ADDR2 <<<$(IFS=";"; echo $IN)
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:44
W Bash, punktoodporny sposób, który będzie działał nawet jeśli zmienna zawiera nowe linie:
IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
Zobacz:
$ in=$'one;two three;*;there is\na newline\nin this field'
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two three" [2]="*" [3]="there is
a newline
in this field")'
Sztuczka, aby to zadziałało, polega na użyciu -d
opcji read
(delimiter) z pustym delimiterem, tak aby read
była zmuszona odczytać wszystko, co jest karmione. I karmimy read
dokładnie zawartością zmiennej in
, bez kończącej się nowej linii dzięki printf
. Zauważ, że ustawiamy również ogranicznik w printf
, aby upewnić się, że łańcuch przechodzi do read
ma ogranicznik spływu. Bez niego, read
przycinałby potencjalne końcowe puste pola:
$ in='one;two;three;' # there's an empty field
$ IFS=';' read -d '' -ra array < <(printf '%s;\0' "$in")
$ declare -p array
declare -a array='([0]="one" [1]="two" [2]="three" [3]="")'
Końcowe puste pole jest zachowane.
Aktualizacja dla Bash≥4.4
Od wersji Bash 4.4 wbudowany mapfile
(aka readarray
) obsługuje opcję -d
określającą ogranicznik. Stąd inny sposób kanoniczny to:
mapfile -d ';' -t array < <(printf '%s;' "$in")
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-10-27 16:03:48
A może ta jedna linijka, jeśli nie używasz tablic:
IFS=';' read ADDR1 ADDR2 <<<$IN
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-09-13 20:10:42
Oto czysty 3-liner:
in="foo@bar;bizz@buzz;fizz@buzz;buzz@woof"
IFS=';' list=($in)
for item in "${list[@]}"; do echo $item; done
Gdzie IFS
delimit słowa oparte na separatorze i ()
jest używany do tworzeniatablicy . Następnie [@]
jest używany do zwracania każdego elementu jako osobnego słowa.
Jeśli masz jakiś kod po tym, musisz również przywrócić $IFS
, np. unset IFS
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-26 10:26:38
Bez ustawiania IFS
Jeśli masz tylko jeden dwukropek możesz to zrobić:
a="foo:bar"
b=${a%:*}
c=${a##*:}
Otrzymasz:
b = foo
c = bar
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-08-01 13:15:07
Jest taki prosty i inteligentny sposób:
echo "add:sfff" | xargs -d: -i echo {}
Ale musisz użyć gnu xargs, BSD xargs cant support-d delim. Jeśli używasz apple mac jak ja. Możesz zainstalować gnu xargs:
brew install findutils
Then
echo "add:sfff" | gxargs -d: -i echo {}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-09-16 03:34:51
Następująca funkcja Bash / zsh dzieli swój pierwszy argument na separator podany przez drugi argument:
split() {
local string="$1"
local delimiter="$2"
if [ -n "$string" ]; then
local part
while read -d "$delimiter" part; do
echo $part
done <<< "$string"
echo $part
fi
}
Na przykład polecenie
$ split 'a;b;c' ';'
a
b
c
To wyjście może być na przykład przekierowane do innych poleceń. Przykład:
$ split 'a;b;c' ';' | cat -n
1 a
2 b
3 c
W porównaniu z innymi podanymi rozwiązaniami, ten ma następujące zalety:
IFS
nie jest przesłonięta: ze względu na dynamiczne zakresy nawet zmiennych lokalnych, przesłonięcieIFS
nad pętlą powoduje wyciek nowej wartości do wywołań funkcji wykonywanych z pętli.Tablice nie są używane: odczyt ciągu znaków do tablicy za pomocą
read
wymaga znacznika-a
W Bash i-A
w zsh.
W razie potrzeby, funkcję można umieścić w skrypcie w następujący sposób:
#!/usr/bin/env bash
split() {
# ...
}
split "$@"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-06-13 18:24:31
To najprostszy sposób.
spo='one;two;three'
OIFS=$IFS
IFS=';'
spo_array=($spo)
IFS=$OIFS
echo ${spo_array[*]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-02-28 08:18:47
IN="[email protected];[email protected]"
IFS=';'
read -a IN_arr <<< "${IN}"
for entry in "${IN_arr[@]}"
do
echo $entry
done
Wyjście
[email protected]
[email protected]
System : Ubuntu 12.04.1
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-25 12:55:51
Możesz zastosować awk w wielu sytuacjach
echo "[email protected];[email protected]"|awk -F';' '{printf "%s\n%s\n", $1, $2}'
Możesz również użyć tego
echo "[email protected];[email protected]"|awk -F';' '{print $1,$2}' OFS="\n"
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-21 11:34:13
Jeśli nie ma miejsca, dlaczego nie to?
IN="[email protected];[email protected]"
arr=(`echo $IN | tr ';' ' '`)
echo ${arr[0]}
echo ${arr[1]}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-24 13:13:57
Są tu fajne odpowiedzi (errator esp.), ale dla czegoś analogicznego do podziału na inne języki - czyli to co miałem na myśli w pierwotnym pytaniu-ustaliłem to:
IN="[email protected];[email protected]"
declare -a a="(${IN/;/ })";
Teraz ${a[0]}
, ${a[1]}
, itp. są takie, jakich można się spodziewać. Użyj ${#a[*]}
dla liczby terminów. Albo do iteracji, oczywiście:
for i in ${a[*]}; do echo $i; done
WAŻNA UWAGA:
To działa w przypadkach, gdy nie ma miejsca, o które można się martwić, co rozwiązało mój problem, ale może nie rozwiązać Twojego. Idź z $IFS
rozwiązanie (- y) w takim przypadku.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-21 20:50:45
Użyj wbudowanego set
, aby załadować tablicę$@
:
IN="[email protected];[email protected]"
IFS=';'; set $IN; IFS=$' \t\n'
Zatem zaczynamy imprezę:
echo $#
for a; do echo $a; done
ADDR1=$1 ADDR2=$2
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-30 03:10:43
Dwie alternatywy bourne ' a, gdzie żadna z nich nie wymaga tablic bash:
Przypadek 1: zachowaj porządek i prostotę: użyj znaku nowego wiersza jako separatora rekordów... np.
IN="[email protected]
[email protected]"
while read i; do
# process "$i" ... eg.
echo "[email:$i]"
done <<< "$IN"
Uwaga: w tym pierwszym przypadku żaden pod-proces nie jest rozwidlony, aby pomóc w manipulacji listą.
Pomysł: może warto używać NL szeroko wewnętrznie , i tylko konwertować na inny RS podczas generowania końcowego wyniku zewnętrznie.
Przypadek 2 : użycie"; " jako rekordu separator... np.
NL="
" IRS=";" ORS=";"
conv_IRS() {
exec tr "$1" "$NL"
}
conv_ORS() {
exec tr "$NL" "$1"
}
IN="[email protected];[email protected]"
IN="$(conv_IRS ";" <<< "$IN")"
while read i; do
# process "$i" ... eg.
echo -n "[email:$i]$ORS"
done <<< "$IN"
W obu przypadkach lista podrzędna może być tworzona w ramach pętli jest trwała po zakończeniu pętli. Jest to przydatne podczas manipulowania listami w pamięci, zamiast przechowywania list w plikach. {p. s. keep calm and carry on B -)}
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-02 06:45:57
Oprócz fantastycznych odpowiedzi, które zostały już dostarczone, jeśli jest to tylko kwestia wydrukowania danych, możesz rozważyć użycie awk
:
awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
Ustawia separator pól na ;
, tak aby mógł przechodzić przez pola za pomocą pętli for
i odpowiednio drukować.
Test
$ IN="[email protected];[email protected]"
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "$IN"
> [[email protected]]
> [[email protected]]
Z innym wejściem:
$ awk -F";" '{for (i=1;i<=NF;i++) printf("> [%s]\n", $i)}' <<< "a;b;c d;e_;f"
> [a]
> [b]
> [c d]
> [e_]
> [f]
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-08 10:21:45
W powłoce Androida większość proponowanych metod po prostu nie działa:
$ IFS=':' read -ra ADDR <<<"$PATH"
/system/bin/sh: can't create temporary file /sqlite_stmt_journals/mksh.EbNoR10629: No such file or directory
Co działa to:
$ for i in ${PATH//:/ }; do echo $i; done
/sbin
/vendor/bin
/system/sbin
/system/bin
/system/xbin
Gdzie //
oznacza globalną wymianę.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-19 22:27:16
/ Align = "left" /
Oto moja odpowiedź!DELIMITER_VAL='='
read -d '' F_ABOUT_DISTRO_R <<"EOF"
DISTRIB_ID=Ubuntu
DISTRIB_RELEASE=14.04
DISTRIB_CODENAME=trusty
DISTRIB_DESCRIPTION="Ubuntu 14.04.4 LTS"
NAME="Ubuntu"
VERSION="14.04.4 LTS, Trusty Tahr"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 14.04.4 LTS"
VERSION_ID="14.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
EOF
SPLIT_NOW=$(awk -F$DELIMITER_VAL '{for(i=1;i<=NF;i++){printf "%s\n", $i}}' <<<"${F_ABOUT_DISTRO_R}")
while read -r line; do
SPLIT+=("$line")
done <<< "$SPLIT_NOW"
for i in "${SPLIT[@]}"; do
echo "$i"
done
Dlaczego takie podejście jest dla mnie" najlepsze"?
Z dwóch powodów:
- robisz nie musisz uciekać ogranicznik;
- nie będziesz miał problemu z pustymi spacjami. Wartość zostanie odpowiednio oddzielona w tablicy!
[]'s
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-04-04 20:22:07
Jednowierszowy podział łańcucha oddzielonego znakiem"; " na tablicę to:
IN="[email protected];[email protected]"
ADDRS=( $(IFS=";" echo "$IN") )
echo ${ADDRS[0]}
echo ${ADDRS[1]}
To ustawia tylko IFS w podkładzie, więc nie musisz się martwić o zapisanie i przywrócenie jego wartości.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-11-29 22:02:13
IN='[email protected];[email protected];Charlie Brown <[email protected];!"#$%&/()[]{}*? are no problem;simple is beautiful :-)'
set -f
oldifs="$IFS"
IFS=';'; arrayIN=($IN)
IFS="$oldifs"
for i in "${arrayIN[@]}"; do
echo "$i"
done
set +f
Wyjście:
[email protected]
[email protected]
Charlie Brown <[email protected]
!"#$%&/()[]{}*? are no problem
simple is beautiful :-)
Explanation: Simple assignment using parenthesis () converts semicolon separated list into a array provided you have correct IFS while doing that. Standard dla pętli obsługuje poszczególne elementy w tej tablicy jak zwykle. Zauważ, że lista podana dla zmiennej IN musi być" twarda", czyli z pojedynczymi wskazami.
IFS musi zostać zapisane i przywrócone, ponieważ Bash nie traktuje przypisania w taki sam sposób jak polecenia. Alternatywnym obejściem jest owinięcie przypisanie wewnątrz funkcji i wywołanie tej funkcji ze zmodyfikowanym IFS. W takim przypadku oddzielne zapisywanie / przywracanie If nie jest konieczne. Dzięki za" Bize " za wskazanie tego.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-04-19 22:28:46
Może nie najbardziej eleganckie rozwiązanie, ale działa z *
i spacjami:
IN="bla@so me.com;*;[email protected]"
for i in `delims=${IN//[^;]}; seq 1 $((${#delims} + 1))`
do
echo "> [`echo $IN | cut -d';' -f$i`]"
done
Wyjścia
> [bla@so me.com]
> [*]
> [[email protected]]
Inny przykład (ograniczniki na początku i końcu):
IN=";bla@so me.com;*;[email protected];"
> []
> [bla@so me.com]
> [*]
> [[email protected]]
> []
W zasadzie usuwa każdy znak inny niż ;
tworząc delims
np. ;;;
. Następnie wykonuje for
pętlę od 1
do number-of-delimiters
liczoną przez ${#delims}
. Ostatnim krokiem jest bezpieczne uzyskanie $i
th części za pomocą cut
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-26 12:20:31