[英]Read 3 output lines into 3 variables in bash
我有一個生成3行輸出的命令,例如
$ ./mycommand
1
asdf
qwer zxcv
我想將這3行分配給3個不同的變量($ a,$ b,$ c),這樣
$ echo $a
1
$ echo $b
asdf
$ echo $c
qwer zxcv
我熟悉while循環方法,該方法通常用於一次從包含3行的輸出中讀取3行。 但是,考慮到我的命令只會輸出3行,這似乎還不夠優雅。
我嘗試使用IFS=
的值和read -rabc
選項的各種組合,將命令輸出作為stdin發送,但是我只能將其設置為第一行到第一個變量。 一些例子:
IFS= read -r a b c < <(./mycommand)
IFS=$'\n' read -r a b c < <(./mycommand)
IFS= read -r -d $'\n' < <(./mycommand)
如果我修改命令以使三行用空格而不是換行符隔開,只要正確地引用每行的前面,我就可以成功使用此變體:
read -r a b c < <(./mycommand)
盡管這對於我當前的項目有用,但仍然令我感到困惑,我無法使它以其他方式工作。 因此,我想知道是否有人可以通過3行輸出來查看和解釋我最初嘗試中缺少的內容。
如果要從三行讀取數據,請使用三讀:
{ read -r a; read -r b; read -r c; } < <(./mycommand)
read
讀取大量數據,然后將其拆分。 您無法使它正常工作,因為您的塊始終都是單行。
較新的BASH版本支持mapfile
命令。 使用它,您可以將所有行讀入數組:
mapfile -t ary < <(./command)
檢查數組內容:
declare -p ary
declare -a ary='([0]="1" [1]="asdf" [2]="qwer zxcv")'
也許這種解釋對您有用。
...仍然令我煩惱,我無法使它以其他方式工作。 因此,我想知道是否有人可以通過3行輸出來查看和解釋我最初嘗試中缺少的內容。
簡單: read
僅適用於一行(默認情況下)。 這個:
#!/bin/bash
mycommand(){ echo -e "1\nasdf\nqwer zxcv"; }
read a b c < <(mycommand)
printf 'first : %s\nsecond : %s\nthird : %s\n' "$a" "$b" "$c"
將打印:
first : 1
second :
third :
但是,使用空字符將捕獲整個字符串(在上面替換此行):
read -d '' a b c < <(mycommand)
將打印:
first : 1
second : asdf
third : qwer zxcv
read
命令吸收了命令的全部輸出,並被分解為具有IFS默認值的部分: Space Tab Enter 。
在此特定示例中,該方法正確運行,因為最后一個值是具有多個“部分”的值。
但是這種處理非常脆弱。 例如:該命令的其他可能輸出,對變量的分配將中斷:
mycommand(){ echo -e "1 and 2\nasdf and dfgh\nqwer zxcv"; }
將輸出(不正確):
first : 1
second : and
third : 2
asdf and dfgh
qwer zxcv
處理很脆。 為了使其健壯,我們需要使用循環。 但是您說那是您已經知道的:
#!/bin/bash
mycommand(){ echo -e "1 and 2\nasdf and dfgh\nqwer zxcv"; }
i=0; while read arr[i]; do ((i++)); done < <(mycommand)
printf 'first : %s\nsecond : %s\nthird : %s\n' "${arr[0]}" "${arr[1]}" "${arr[2]}"
哪個將(正確)打印:
first : 1 and 2
second : asdf and dfgh
third : qwer zxcv
但是,可以使用bash命令readarray簡化循環:
#!/bin/bash
mycommand(){ echo -e "1 and 2\nasdf and dfgh\nqwer zxcv"; }
readarray -t arr < <(mycommand)
printf 'first : %s\nsecond : %s\nthird : %s\n' "${arr[0]}" "${arr[1]}" "${arr[2]}"
並且使用printf“ loop”將使該結構適用於任何數量的輸入行:
#!/bin/bash
mycommand(){ echo -e "1 and 2\nasdf and dfgh\n*\nqwer zxcv"; }
readarray -t arr < <(mycommand)
printf 'value : %s\n' "${arr[@]}"
希望這會有所幫助。
編輯
在bash中,幾乎不使用null。 具體來說,在大多數情況下,零值都會被靜默刪除。 該解決方案確實具有該限制。
在輸入中包含null:
mycommand(){ echo -e "1 and 2\nasdf and dfgh\n\000\n*\nqwer zxcv"; }
將進行簡單的read -r -d ''
以使輸入達到第一個空值(理解為空值,例如具有八進制000的字符)。
echo "test one:"; echo
echo "input"; echo
mycommand | od -tcx1
echo "output"; echo
read -r -d '' arr < <(mycommand)
echo "$arr" | od -tcx1
將此作為輸出:
test one:
input
0000000 1 a n d 2 \n a s d f a n d
31 20 61 6e 64 20 32 0a 61 73 64 66 20 61 6e 64
0000020 d f g h \n \0 \n * \n q w e r z
20 64 66 67 68 0a 00 0a 2a 0a 71 77 65 72 20 7a
0000040 x c v \n
78 63 76 0a
0000044
output
0000000 1 a n d 2 \n a s d f a n d
31 20 61 6e 64 20 32 0a 61 73 64 66 20 61 6e 64
0000020 d f g h \n
20 64 66 67 68 0a
0000026
顯然,讀取捕獲的值停止在第一個八進制000。
坦率地說,這是可以預期的。
我必須報告,然而,readarray 不會在八進制000停止,但只是默默地刪除它(通常一個外殼性狀)。
運行此代碼:
#!/bin/bash
mycommand(){ echo -e "1 and 2\nasdf and dfgh\n\000\n*\nqwer zxcv"; }
echo "test two:"; echo
echo "input"; echo
mycommand | od -tcx1
echo "output"; echo
readarray -t arr < <(mycommand)
printf 'value : %s\n' "${arr[@]}"
echo
printf 'value : %s\n' "${arr[@]}"|od -tcx1
呈現此輸出:
test two:
input
0000000 1 a n d 2 \n a s d f a n d
31 20 61 6e 64 20 32 0a 61 73 64 66 20 61 6e 64
0000020 d f g h \n \0 \n * \n q w e r z
20 64 66 67 68 0a 00 0a 2a 0a 71 77 65 72 20 7a
0000040 x c v \n
78 63 76 0a
0000044
output
value : 1 and 2
value : asdf and dfgh
value :
value : *
value : qwer zxcv
0000000 v a l u e : 1 a n d 2 \n
76 61 6c 75 65 20 3a 20 31 20 61 6e 64 20 32 0a
0000020 v a l u e : a s d f a n d
76 61 6c 75 65 20 3a 20 61 73 64 66 20 61 6e 64
0000040 d f g h \n v a l u e : \n v
20 64 66 67 68 0a 76 61 6c 75 65 20 3a 20 0a 76
0000060 a l u e : * \n v a l u e :
61 6c 75 65 20 3a 20 2a 0a 76 61 6c 75 65 20 3a
0000100 q w e r z x c v \n
20 71 77 65 72 20 7a 78 63 76 0a
0000113
也就是說,零000或僅\\ 0被靜默刪除。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.