wc -m似乎在bash中循环时停止

Art*_*man 0 unix bash shell wc

我正在UNIX上做一个入门课程 - 其中一部分是bash脚本.我似乎已经理解了这些概念,但在这个特殊的问题上我无法解决这个问题.

我有一个txt文件,包含1列随机用户名.然后将该txt文件用作我的bash脚本的参数,理想情况下使用用户名来获取页面并计算该页面上的字符数.如果页面成功获取,则随后将字符计数与用户名一起保存在不同的txt文件中.

这是一个代码:

#!/bin/bash
filename=$1

while read username; do
    curl -fs "http://example.website.domain/$username/index.html"
    if [ $? -eq 0 ]
    then
        x=$(wc -m)
        echo "$username $x" > output.txt
    else
        echo "The page doesn't exist"
    fi
done < $filename
Run Code Online (Sandbox Code Playgroud)

现在我遇到的问题是,在一次成功获取之后,它会对字符进行计数,将它们输出到文件中,然后完成循环并退出程序.如果我特意删除"wc -m"位,代码运行完全正常.

问:是否应该发生这种情况,我应该如何解决这个问题呢?或者我在其他地方犯了错误?

Pos*_*shi 5

显示的代码不符合您的想法(并在您的问题中声明).

您的curl命令将获取Web并将其抛出到stdout:您不会保留此信息以供将来使用.然后,你wc没有任何参数,所以它开始从stdin读取.在stdin中,您有来自的用户名列表$filename,因此计算的数字不是Web的字符,而是文件的剩余字符.一旦考虑到这一点,stdin中没有任何东西可以被读取,所以循环结束是因为它到达了文件的末尾.

您正在寻找类似的东西:

#!/bin/bash
filename="$1"

set -o pipefail
rm -f output.txt
while read username; do
    x=$(curl -fs "http://example.website.domain/$username/index.html" | wc -m)
    if [ $? -eq 0 ]
    then
        echo "$username $x" >> output.txt
    else
        echo "The page doesn't exist"
    fi
done < "$filename"
Run Code Online (Sandbox Code Playgroud)

这里,获取的页面直接输入到wc.如果curl失败,你将看不到(默认情况下,一系列管道命令的退出代码是最后一个命令的退出代码),因此我们使用set -o pipefail一个不同于零的值来获取最右边退出代码的退出代码.现在您可以检查一切是否正常,在这种情况下,您可以编写结果.

我还添加了一个rm输出文件,以确保我们不会增加现有的输出文件,并将重定向更改为输出文件,以避免在每次迭代时重新创建文件,最后以最后一次迭代的结果(感谢@tripleee注意到这一点).

更新(按流行要求):

模式:

<cmd>
if [ $? -eq 0 ]...
Run Code Online (Sandbox Code Playgroud)

通常是一个坏主意.最好去:

if <cmd>...
Run Code Online (Sandbox Code Playgroud)

所以如果切换到以下情况会更好:

if x=$(curl -fs "http://example.website.domain/$username/index.html" | wc -m); then
    echo...
Run Code Online (Sandbox Code Playgroud)