看板 Linux 關於我們 聯絡資訊
※ 引述《LIAR (玻璃做的大叔)》之銘言: : 我需要在bash裡面把上萬筆的資料丟到array中,我用過兩種方式 : mapfile -t -s 1 lines<<<$(ls -lrt /tmp/) : echo ${lines[@]} 改成這樣就好啊: mapfile -t -s 1 lines <<< "$(ls -lrt /tmp/)" 用雙引號包起來。 因為 ls -ltr /tmp 是很多行輸出結果,要考慮實際後續資料傳入給 mapfile 命令時候情況。 簡單這樣說好了: result=$(cat /etc/passwd) 後續你用 echo $result 與 echo "$result" 結果不一樣的, 前者換行字元帶入顯示就變成 space 空白字元了。你可以用: echo "$result" | hexdump -C | head echo $result" | hexdump -C | head 自己看一下差別。 那原本你使用的命令為何結果是空的?依據 mapfile 參數說明: mapfile: -s count Discard the first COUNT lines read. -t Remove a trailing newline from each line read. 你用了-s 1 把第一行吃掉忽略,而剛好結果是一整行內容,所以結果就是空的。 你把 -s 1 拿掉可以拿到結果,但是 mapfile 沒有讀取實際換行字元,但是資料 沒有多行所以最後產生 array 也是破功... : 新版的clonezilla這個命令是有效的。2.4.5-23版或centos則是空的。 : mapfile -t -s 1 lines< <(ls -lrt /tmp/) : echo ${lines[@]} : 這樣有東西。 這又是其他的語法了。實際上運作就是: 1. 執行 ls -lrt /tmp 輸出結果,應對到 /dev/fd/<xxx> 這種 named FIFO 檔案 2. 執行 mapfile -t -s 1 lines < /dev/fd/<xxx> 所以運作正常沒特別地方,因為等於類似: 1. ls -lrt /tmp > myfile.txt 2. mapfile -t -s 1 lines < myfile.txt 只是 myfile.txt 需要自己刪除。 : 那個<<<中間兩個或三個沒有,和$的有無是搭配的,不能混用,不然會錯。 : 我看鳥哥的教學,我只用過 $(command) 這種方式。但反而這個寫法無法得到array。 : 雖然有爬文找redirection和Here Strings的解釋,但我還是搞不懂兩種寫法的差別, : 而且也搞不懂clonezilla新舊版的執行結果為何也不同。 : 請問有人知道兩種寫法的差別和原理嗎? -- ※ 發信站: 批踢踢實業坊(ptt.cc), 來自: 36.236.153.239 ※ 文章網址: https://www.ptt.cc/bbs/Linux/M.1519496495.A.5C7.html
hijkxyzuw: 為什麼不是 ls -lrt /tmp/ | mapfile -t -s 1 lines ? 02/25 11:33
因為需求是 mapfile 這個 shell 內建命令產生 array 變數 並且變數要在 current shell 環境下來使用 若這樣用你提到的命令方式的話執行 mapfile 當下的 shell 並非 current shell 而是另外一個新的 subshell 去執行運作,當下執行 時候的確有產生 lines 變數,但是結果是放在當時候的 subshell 內, 跑完之後結束之後回到原本 shell 無法取得該變數結果的。 就像是這樣用: echo 1 2 3 | read n1 n2 n3 使用 echo $n1 $n2 $n3 是空值沒該變數的 改成這樣就好: read n1 n2 n3 <<< $(echo 1 2 3) or: read n1 n2 n3 < <(echo 1 2 3) ※ 編輯: kenduest (122.117.155.17), 02/25/2018 17:12:57
hijkxyzuw: 了,難怪我找不到 mapfile 這個命令 02/25 18:04
kenduest: 目前都用 readarray 命令取代了 印象中 02/25 18:40
Hevak: 推 02/26 00:44