我正在嘗試將字串轉換string=11111001
為數組,我可以通過調用相應的數組索引來訪問它,例如
arr[0]=1, arr[1]=0
我是 shell 腳本新手,從我讀到的內容來看,它沒有分隔符,我陷入了困境。
有人能幫我嗎?
答案1
bash
已經透過字串切片的方式實現了這種形式:
$ word="word"
$ printf "%s\n" "${word:0:1}"
w
$ printf "%s\n" "${word:1:1}"
o
其語法為${variable:start:length}
, 並將傳回下一個length
字元開始於start
ᵗʰ 字符(零索引)。
$ printf "%s\n" "${word:2:2}"
rd
答案2
為了完整起見,使用zsh
, 將字串拆分為:
它是特點成分:
chars=( ${(s[])string} )
(如果$string
包含不構成有效字元部分的字節,則每個位元組仍將儲存為單獨的元素)
它是位元組成分
您可以執行相同的操作,但在取消設定後多位元組選項,例如在本地匿名函數中:
(){ set -o localoptions +o multibyte
bytes=( ${(s[])string} )
}
它是字素簇選民。
您可以使用 PCRE 的功能將它們與\X
:
zmodload zsh/pcre
(){
graphemes=()
local rest=$string match
pcre_compile -s '(\X)\K.*'
while pcre_match -v rest -- "$rest"; do
graphemes+=($match[1])
done
}
(假設輸入包含在區域設定的字元對應中正確編碼的文字)。
對於string=$'Ste\u0301phane'
,這些給出:
chars=( S t e ́ p h a n e )
bytes=( S t e $'\M-L' $'\M-\C-A' p h a n e )
graphemes=( S t é p h a n e )
由於e
+ U+0301 字素簇(顯示設備通常表示與é
U+00E9 預組合的等效項相同)由2 個字元(U+0065 和U+0301)組成,其中在使用UTF-8 作為其字元映射的語言環境中,第一個在一個位元組 (0x65) 上編碼,第二個在兩個位元組 (0xcc 0x81,也稱為 Meta-L 和 Meta-Ctrl-A) 上編碼。
對於僅由 ASCII 字元組成的字串(例如您的 )11111001
,這三個字元是等效的。
請注意,與zsh
ksh/bash 以外的所有其他 shell 一樣,陣列索引從 1 開始,而不是 0。
答案3
您可以將字串拆分為單一字元:
string=11111001
echo "$string" | grep -o .
並將它們作為數組讀回:
readarray -t arr <<<"$(grep -o . <<<"$string")"
那麼,當然,每個字元將位於arr
數組的每個索引處。
$ declare -p arr
declare -a arr=([0]="1" [1]="1" [2]="1" [3]="1" [4]="1" [5]="0" [6]="0" [7]="1")
但是,如果 bash 可以直接存取每個單獨的字符,為什麼要建立一個新數組,如下所示:
$ string=11111001
echo "${string:5:1}" "${string:7:1}"
0 1
閱讀${parameter:offset:length}
有關man bash
.
答案4
在bash
4.4+ 中,由於bash
無論如何都無法在其變數中儲存 NUL 字符,您可以調用不同的實用程式來進行分割並列印 NUL 分隔的結果,您可以使用readarray -td ''
.
如果您的系統附帶了 GNU 實現grep
,您可以這樣做:
readarray -td '' bytes < <(printf %s "$string" | LC_ALL=C grep -zo .)
readarray -td '' chars < <(printf %s "$string" | grep -zo .)
readarray -td '' graphemes < <(printf %s "$string" | grep -zPo '\X')
除第一個之外的所有位元組都將跳過不構成語言環境中有效字元一部分的位元組(至少在 GNU grep
3.4 中)。例如,string=$'Ste\u0301phane \\\xf0\x80z.'
在 UTF-8 語言環境中(尾隨部分不形成有效的 UTF-8),給出:
declare -a bytes=([0]="S" [1]="t" [2]="e" [3]=$'\314' [4]=$'\201' [5]="p" [6]="h" [7]="a" [8]="n" [9]="e" [10]=" " [11]="\\" [12]=$'\360' [13]=$'\200' [14]="z" [15]=".")
declare -a chars=([0]="S" [1]="t" [2]="e" [3]="́" [4]="p" [5]="h" [6]="a" [7]="n" [8]="e" [9]=" " [10]="\\" [11]="z" [12]=".")
declare -a graphemes=([0]="S" [1]="t" [2]="é" [3]="p" [4]="h" [5]="a" [6]="n" [7]="e" [8]=" " [9]="\\" [10]="z" [11]=".")
如果不在 GNU 系統上,並且假設$string
包含有效的 UTF-8 文本,則可以使用perl
:
readarray -td '' bytes < <(perl -0le 'print for split "", shift' -- "$string")
readarray -td '' chars < <(perl -CSA -0le 'print for split "", shift' -- "$string")
readarray -td '' graphemes < <(perl -CSA -0le 'print for shift =~ /\X/g' -- "$string")