2012-07-31 14 views
13

Mam ciąg w następującym formacie:Jak podzielić wieloliniowy ciąg zawierający znaki " n" na tablicę ciągów w bash?

I'm\nNed\nNederlander 
I'm\nLucky\nDay 
I'm\nDusty\nBottoms 

Chciałbym przenieść to do tablicy ciągów linii przez linię takie, że:

$ echo "${ARRAY[0]}" 
I'm\nNed\nNederlander 

$ echo "${ARRAY[1]}" 
I'm\nLucky\nDay 

$ echo "${ARRAY[2]}" 
I'm\nDusty\nBottoms 

Jednak jestem napotyka problemy z "\ n" znakami w samym ciągu. Są one reprezentowane w łańcuchu jako dwa oddzielne znaki, ukośnik odwrotny i "n", ale kiedy próbuję zrobić podział tablicy, interpretuje się je jako znaki nowej linii. W związku z tym typowe dzielenie ciągów za pomocą IFS nie działa.

Na przykład:

$ read -a ARRAY <<< "$STRING" 
$ echo "${#ARRAY[@]}" # print number of elements 
2 

$ echo "${ARRAY[0]}" 
I'mnNednNederla 

$ echo "${ARRAY[1]}" 
der 
+0

BTW, czy ktoś wie jak to naprawić SE okropne formatowanie powyższego kodu? –

+0

"Okropne formatowanie" spowodowane jest tym, że apostrofy są interpretowane jako pojedyncze cytaty (które powinny być zrównoważone). Użyj tagów "block quote" zamiast tagów "code". – twalberg

Odpowiedz

24

Domyślnie read wbudowane pozwala \ uciec znaków. Aby wyłączyć to zachowanie, użyj opcji -r. Nie często można znaleźć przypadek, w którym nie chcesz używać -r.

string="I'm\nNed\nNederlander 
I'm\nLucky\nDay 
I'm\nDusty\nBottoms" 

arr=() 
while read -r line; do 
    arr+=("$line") 
done <<< "$string" 

aby zrobić to w jednej linii (tak jak próbowali z read -a), faktycznie wymaga mapfile w bash v4 lub wyższa:

mapfile -t arr <<< "$string" 
+0

tak dla pliku mapfile oneliner :) –

12

mapfile jest bardziej elegancki, ale jest to możliwe to zrobić w jednej linii (brzydki) z read (przydatne, jeśli używasz wersji starszej niż bash 4):

IFS=$'\n' read -d '' -r -a arr <<< "$string" 
+0

Rzeczywiście, opcja -d wydaje się kluczowa, aby to zadziałało. –

+0

Jedno zastrzeżenie, o którym nie wiedziałem, kiedy to napisałem: status wyjścia będzie niezerowy, ponieważ ciąg tutaj nigdy się nie zakończy oczekuje się znaku pustego, takiego jak 'read -d '''. – chepner

Powiązane problemy