簡體   English   中英

將3條輸出行讀入bash中的3個變量

[英]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中):

我必須報告,然而,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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM