將變數名稱與輸出字串分開,不含空格

將變數名稱與輸出字串分開,不含空格

我有以下我想要的程式碼片段:

迭代5次循環;
從文件中取得一行(每次迭代我都需要取得下一行);
使用該行作為文件的標題;
在其開頭添加一個時間戳記;
使用該行作為 ping 的參數;列印一些句子,通知使用者代碼的進度;

迭代已經起作用了。
如果我跳過 sed 部分,一切都會正常,但我對同一目標執行 ping 5 次。
檔案hosts.txt 的每一行都有一個我打算對其進行ping 操作的IP 位址。

for ((i>=1;i<=5;i++))  
do  
sed -n "$i p" hosts.txt | read output  
    touch "$output.txt"  
    date >> "$output.txt"  
    printf "\nComeçando o teste de $output."  
    printf "\nTeste em andamento."  
    ping -c 10 -i 1 "$output" >> "$output.txt"  
done  

我相信問題是我對 sed 文法做錯了。如果我直接嘗試 bash sed -n 1p hosts,我會得到第一行。但由於我需要該數字為 $i,如果我將 $i 放在 p 之前,bash 會將 ip 解釋為變量,而不是變量 i 加上其後的參數 p。

我怎麼能糾正這種行為並且不再弄亂這件事?

答案1

我假設你正在使用 bash 所以這應該會更好:

for ((i=1;i<=5;i++))  
do  
    sed -n "$i p" hosts.txt | (
        read output  
        touch "$output.txt"  
        date >> "$output.txt"  
        printf "\nComeçando o teste de $output."  
        printf "\nTeste em andamento."  
        ping -c 10 -i 1 "$output" >> "$output.txt"  
    )
done 

您遇到的問題是bash,就像大多數外部 shell 解釋器一樣ksh,將所有管道組件放入子 shell 中,因此output變數在設定後會立即遺失。

另請注意,我更正了您的for循環,該循環具有未定義的行為,因為i變數未初始化。

答案2

正如您所觀察到的,問題是 和i都是ip有效的變數名稱。因此,如果您想使用$i緊接在字元 後面的值p,您可以使用大括號來清楚地界定變數名稱的開始和結束位置:

sed -n "${i}p" hosts.txt | read output

答案3

一個稍微簡單的解決方案是

for ((i=1; i<=5; i++))
do
    read output
    date >> "$output.txt"
    printf "\nComeçando o teste de %s." "$output"
    printf "\nTeste em andamento."
    ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt

請注意< hosts.txt最後一行末尾的 ,位於done.這將打開hosts.txt一次並僅讀取其中的前五行。正如 don_crissti 所提到的,sed … hosts.txt | read output 在循環中執行意味著您正在讀取hosts.txt文件五次。由於read output與循環的其餘部分並行(不在管道中),因此循環中的其餘程式碼將有權存取output從文件中讀取的值。另外(正如 don 也指出的那樣),你不需要touch; 將創造command>>filefile如果它尚不存在。

請注意,如果您的文件之一hostname.txt已存在,則此程式碼會將新資訊附加到其中。如果您想丟棄舊數據並從頭開始,請執行date > "$output.txt"而不是date >> "$output.txt".

請小心將未知資料直接傳遞給printf.萬一(不太可能?)您的「主機名稱」之一包含%,您的程式碼將導致該名稱出現亂碼。最好將外部資料傳遞給%s(列印字串)。

你沒有說是否要只讀取文件的前五行hosts.txt然後停止,或者是否要讀取整個文件,而你恰好知道它有五行長。如果你想讀取整個文件,只需這樣做

while read output
do
    date >> "$output.txt"
    printf "\nComeçando o teste de %s." "$output"
    printf "\nTeste em andamento."
    ping -c 10 -i 1 "$output" >> "$output.txt"
done < hosts.txt

當到達文件末尾時,該read output語句將失敗,循環將終止。

相關內容