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.

Author: codeforester, 2009-05-28

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"
 958
Author: Johannes Schaub - litb,
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:

  1. jeśli oryginalny łańcuch znaków ma spacje, musisz użyć IFS :
    • IFS=':'; arrIN=($IN); unset IFS;
  2. jeśli oryginalny łańcuch ma spacje i ogranicznik jest nową linią, możesz ustawić IFS za pomocą:
    • IFS=$'\n'; arrIN=($IN); unset IFS;
 768
Author: palindrom,
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.

 214
Author: Chris Lutz,
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!
 134
Author: F. Hauri,
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.

 85
Author: DougW,
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]}" 

Źródło

 81
Author: BLeB,
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
 75
Author: Steven Lizarazo,
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
 59
Author: lothar,
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.

 58
Author: Ashok,
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.

 32
Author: Tony,
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)
 25
Author: nickjb,
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")
 23
Author: gniourf_gniourf,
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
 18
Author: Darron,
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.

 17
Author: kenorb,
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
 16
Author: Emilien Brigand,
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 {}
 7
Author: Victor Choy,
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ęcie IFS 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 "$@"
 5
Author: Halle Knast,
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[*]}
 4
Author: Prospero,
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

 3
Author: rashok,
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"
 3
Author: shuaihanhungry,
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]}
 2
Author: ghost,
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.

 2
Author: eukras,
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
 1
Author: jeberle,
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 -)}

 1
Author: NevilleDNZ,
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]
 1
Author: fedorqui,
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ę.

 1
Author: 18446744073709551615,
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:

  1. robisz nie musisz uciekać ogranicznik;
  2. nie będziesz miał problemu z pustymi spacjami. Wartość zostanie odpowiednio oddzielona w tablicy!

[]'s

 1
Author: Eduardo Lucio,
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.

 0
Author: Michael Hale,
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.

 0
Author: ajaaskel,
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 $ith części za pomocą cut.

 0
Author: Petr Újezdský,
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