3 回答

TA貢獻2036條經驗 獲得超8個贊
echo?-e?$lines?|?while?read?line? ????...done
這個while
循環在子shell中執行。因此,一旦子shell退出,您對變量所做的任何更改都將不可用。
相反,您可以使用這里串在主外殼進程中重寫while循環;僅echo -e $lines
將在子shell中運行:
while?read?linedo ????if?[[?"$line"?==?"second?line"?]] ????then ????????foo=2 ????????echo?"Variable?\$foo?updated?to?$foo?inside?if?inside?while?loop" ????fi ????echo?"Value?of?\$foo?in?while?loop?body:?$foo"done?<<<?"$(echo?-e?"$lines")"
你可以擺脫那些相當丑陋的人echo
在上述字符串中,在賦值時立即展開反斜杠序列。lines
。這個$'...'
引用的形式可以在這里使用:
lines=$'first?line\nsecond?line\nthird?line'while?read?line;?do ????...done?<<<?"$lines"

TA貢獻2012條經驗 獲得超12個贊
備選解決辦法:
消去echo
while?read?line;?do...done?<<EOT first?line second?line third?line EOT
在“這里是文檔”中添加回顯。
while?read?line;?do...done?<<EOT $(echo?-e?$lines)EOT
跑echo
背景:
coproc?echo?-e?$lineswhile?read?-u?${COPROC[0]}?line;?do?...done
顯式地重定向到文件句柄(請注意< <
!):
exec?3<?<(echo?-e??$lines)while?read?-u?3?line;?do...done
或者重定向到stdin
:
while?read?line;?do...done?<?<(echo?-e??$lines)
一張是給你的chepner
(消除echo
):
arr=("first?line"?"second?line"?"third?line");for((i=0;i<${#arr[*]};++i))?{?line=${arr[i]};?...}
變量$lines
可以在不啟動新的子shell的情況下轉換為數組。人物\
和n
必須轉換為某個字符(例如,一個真正的新行字符),并使用IFS(內部字段分隔符)變量將字符串拆分為數組元素??梢赃@樣做:
lines="first?line\nsecond?line\nthird?line"echo?"$lines"OIFS="$IFS"IFS=$'\n'?arr=(${lines//\\n/$'\n'}) ?#?ConversionIFS="$OIFS"echo?"${arr[@]}",?Length:?${#arr[*]}set|grep?^arr
結果是
first?line\nsecond?line\nthird?line first?line?second?line?third?line,?Length:?3arr=([0]="first?line"?[1]="second?line"?[2]="third?line")

TA貢獻1859條經驗 獲得超6個贊
描述了管道創建的子shell中設置的變量的一般情況:
E4)如果我將命令的輸出輸送到
read variable
,為什么輸出沒有出現在$variable
讀取命令何時結束?這與Unix進程之間的父-子關系有關。它影響在管道中運行的所有命令,而不僅僅是對
read
。例如,將命令的輸出轉換為while
循環,反復調用read
會導致同樣的行為。管道的每個元素,甚至是內置或shell函數,都運行在單獨的進程中,即運行管道的shell的子進程中。子進程不能影響其父進程的環境。當
read
命令將變量設置為輸入,該變量僅在子shell中設置,而不是在父shell中設置。當子shell退出時,變量的值將丟失。許多以
read variable
可以轉換為命令替換,這將捕獲指定命令的輸出。然后,可以將輸出分配給一個變量:grep?^gnu?/usr/lib/news/active?|?wc?-l?|?read?ngroup可以轉換成
ngroup=$(grep?^gnu?/usr/lib/news/active?|?wc?-l)不幸的是,這并不能將文本拆分到多個變量中,就像給出多個變量參數時的Read一樣。如果需要這樣做,可以使用上面的命令替換將輸出讀入變量并使用bash模式刪除擴展操作符分割變量,或者使用以下方法的一些變體。
例如/usr/local/bin/ipaddr是以下shell腳本:
#!?/bin/shhost?`hostname`?|?awk?'/address/?{print?$NF}'而不是使用
/usr/local/bin/ipaddr?|?read?A?B?C?D若要將本地機器的IP地址分解為單獨的八進制,請使用
OIFS="$IFS"IFS=.set?--?$(/usr/local/bin/ipaddr)IFS="$OIFS"A="$1"?B="$2"?C="$3"?D="$4"但是,請注意,這將改變shell的位置參數。如果你需要它們,你應該在做這件事之前先保存它們。
這是一般的方法-在大多數情況下,您不需要將$IFS設置為不同的值。
其他一些用戶提供的替代方案包括:
read?A?B?C?D?<<?HERE ????$(IFS=.;?echo?$(/usr/local/bin/ipaddr))HERE如果過程替換可用,
read?A?B?C?D?<?<(IFS=.;?echo?$(/usr/local/bin/ipaddr))
添加回答
舉報