将变量名称与输出字符串分开,不带空格

将变量名称与输出字符串分开,不带空格

我有以下我想要的代码片段:

迭代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语句将失败,循环将终止。

相关内容