嘗試使用 while read line 和 echo 進行 bash 大括號擴展(離散數字),不會擴展
我將簡要介紹我所面臨的問題。我正在嘗試編寫的實際應用程序有很多部分,所以我嘗試用一個小例子來隔離我遇到的部分。我的情況涉及文件 ID 號,類似於從目錄或其他東西解析的學生 ID 號的假設列表。
我從什麼開始
為了嘗試並利用
bash
大括號擴展,已解析學生目錄之類的內容以提供以下內容:$ cat student_id_potential_expansions 0000{11,24} 0001{32,38,81} 0002{02,80,81,89,97}
期望的行為
我想使用這個輸入來創建我自己的(Bourne Again)shell 腳本,它看起來像下面這樣。
#!/bin/bash get_transcripts_for_id.sh -id 000011 get_transcripts_for_id.sh -id 000024 get_transcripts_for_id.sh -id 000132 get_transcripts_for_id.sh -id 000133 get_transcripts_for_id.sh -id 000181 get_transcripts_for_id.sh -id 000202 ...
等等
我之前不太擔心命令;我想我會用一個
awk '{print "get_transcripts_for_id.sh -id" $0}' student_id_list > my_shell_script.sh
或一個
sed 's/^\(.*\)$/get_transcripts_for_id.sh -id \1/' student_id_list > my_shell_script.sh
現在,我只是想
student_id_list
從潛在擴展列表中獲取 id 編號列表(從上面)。我想我知道基本問題,我只是不知道如何解決它。我可以得到我想要的列表片段,如下所示:
$ echo 0000{11,24} | tr ' ' '\n' 000011 000024 $ echo 0001{32,38,81} | tr ' ' '\n' 000132 000138 000181 $ echo 0002{02,80,81,89,97} | tr ' ' '\n' 000202 000280 000281 000289 000297
但是,我第一個想到的命令並沒有擴展內容
# doesn't work, as you can see $ while read -r line; do echo $line; done < student_id_potential_expansions 0000{11,24} 0001{32,38,81} 0002{02,80,81,89,97}
我不想只是複制/粘貼每一行。我已經獲得了成百上千的潛在可擴展行 - 這些是由不知道在哪裡的其他人解析的,我無法訪問從記錄中進行原始解析的人。另外,我的每一行都更像
0000009{882,739,861,014,952,611,862,935,976,916,080,697,323,843,840,487,517,407,256,756,374,682,162,930,758,157,770,505,867,233,198,131,917,848,613,247,961,261,616,392,876,747,873,148,844,849,280,626,817,819,174,771,172,284,217,200,018,624,418,292,642,529,755,855,647,317,881,962,975,237,635,805,298,835,053}
我的理解
來自 bash 手冊,第 3.5.1 節
大括號擴展是一種可以生成任意字元串的機制。
…
格式正確的大括號展開必須包含不帶引號的左大括號和右大括號,以及至少一個不帶引號的逗號或有效的序列表達式。任何格式不正確的大括號擴展都保持不變。據我了解,當我閱讀每一行時,我基本上是在給一個字元串提供給 while 循環內的任何內容,即在上面的範例中,我首先給出
$line
as"0000{11,24}"
(注意引號)。進一步進行,就好像我第一次通過循環導致以下命令echo "0000{11,24}"
再一次注意引號,即使它們不在
$line
我的while
循環中。為了看看這是否一致,我執行了以下命令並得到了以下結果:$ echo "0000{11,24}" 0000{11,24} $ echo "0001{32,38,81}" 0001{32,38,81} $ echo "0002{02,80,81,89,97}" 0002{02,80,81,89,97}
因此,據我所知,所有的大括號 (
{
和}
) 和逗號都被引用了——bash 手冊中所說的會導致無效的擴展語句。那麼,主要問題是,我如何取消引用或取消字元串化$line
我讀到的每個內容?我的嘗試/研究
冒著使這篇文章太長的風險,這裡有一些我所做的嘗試。
瀏覽這篇SO 文章,我很確定我的問題不是單詞分離問題。
在
bash
,{}
擴展發生在$
擴展之前,所以我認為除了使用eval
或其他一些技巧來導致兩次通過表達式之外,沒有其他方法可以做到這一點。讓我想到嘗試
$ while read -r line; do eval "$line"; done < student_id_potential_expansions bash: 000011: command not found bash: 000132: command not found bash: 000202: command not found
和
$ while read -r line; do echo $(eval "$line"); done < student_id_potential_expansions bash: 000011: command not found bash: 000132: command not found bash: 000202: command not found
在 shell 嘗試執行(評估)命令之前,似乎只進行了第一次擴展。
我還嘗試了以下命令,查看此處的評論。
$ while read -r line; do expansions=$line; echo $expansions; done < trying_inner_echo.txt $(echo 0000{11,24}) $(echo 0001{32,38,81}) $(echo 0002{02,80,81,89,97}) $ while read -r line; do echo $line; done < trying_inner_echo.txt $(echo 0000{11,24}) $(echo 0001{32,38,81}) $(echo 0002{02,80,81,89,97}) $ while read -r line; do threads=${line}; exec $threads; done < trying_inner_echo.efl bash: exec: $(echo: not found bash: exec: $(echo: not found bash: exec: $(echo: not found $ while read -r line; do threads=${line}; exec "${threads}"; done < trying_inner_echo.txt bash: exec: $(echo 0000{11,24}): not found bash: exec: $(echo 0001{32,38,81}): not found bash: exec: $(echo 0002{02,80,81,89,97}): not found
其他一些嘗試:
$ while read -r line; do echo "$line"; done < student_id_potential_expansions $ while read -r line; do echo "$(echo $line)"; done < student_id_potential_expansions
系統資訊
$ uname -a CYGWIN_NT-10.0 C-D-ENG-E-INT3 2.11.2(0.329/5/3) 2018-11-08 14:34 x86_64 Cygwin $ bash --version GNU bash, version 4.4.12(3)-release (x86_64-unknown-cygwin) Copyright (C) 2016 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html> This is free software; you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. $ systeminfo | sed -n 's/^OS\ *//p' Name: Microsoft Windows 10 Enterprise Version: 10.0.17134 N/A Build 17134 Manufacturer: Microsoft Corporation Configuration: Member Workstation Build Type: Multiprocessor Free
我用了什麼(感謝@EchoMike444)
@EchoMike444 的答案是絕對正確的,讓我到達了我需要去的地方,因此這是公認的答案。由於我使用的內容與答案中出現的內容略有不同,因此我將把它放在這裡(而不是在答案的評論中)。來自評論:
謝謝你把我帶到那裡。當我使用
while read -r line; do eval "echo $line" ## RIGHT! done < student_id_potential_expansions | tr ' ' '\n'
我得到了我正在尋找的輸出。我需要幫助才能到達那裡
echo $(eval "$line") # wrong!
。
訣竅是使用
eval
一個非常小的例子:
( echo '000{90,91}' ; echo '002{10,11}' ; echo '110{50,51}' ) | \ while read L ; do eval "echo $L" | tr ' ' '\n' ; done