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

时间:2019-02-28 13:14:30

标签: bash shell unix 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

现在我这里的问题是,一次成功获取后,它会计算字符,将它们输出到文件中,然后完成循环并退出程序。如果我专门删除“ wc -m”位,则代码运行得很好。

问:这是否应该发生,我应该如何解决该问题以实现我的目标?还是我在其他地方犯了错误?

3 个答案:

答案 0 :(得分:5)

显示的代码没有按照您的想法(并在您的问题中声明)。

您的curl命令获取网络并将其扔到stdout:您没有保留此信息以备将来使用。然后,您的wc没有任何参数,因此它开始从stdin中读取。并且在stdin中,您具有$filename中的用户名列表,因此要计算的数字不是网络字符,而是文件的其余字符。一旦解决了这个问题,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"

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

我还添加了输出文件的<cmd> if [ $? -eq 0 ]... ,以确保我们没有增加现有文件的质量,并将输出文件的重定向更改为附加文件,以避免在每次迭代时重新创建文件并结束最后一次迭代的结果(感谢@tripleee指出了这一点)。

更新(根据普遍要求):

模式:

if <cmd>...

通常是个坏主意。最好去:

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

因此,最好切换到以下位置:

enctype="multipart/form-data"

答案 1 :(得分:1)

默认情况下,wc程序(以及在Linux上可以找到的许多其他实用程序)期望其输入在stdin(标准输入)上提供,并向{{ 1}}(标准输出)。

在您的情况下,您希望stdoutwc调用的结果进行运算。您可以通过将curl的结果存储在变量中并将变量的内容传递到curl

来实现此目的。
wc

或者,您可以将整个命令放在一个管道中,这可能更好(尽管您可能想要data=$(curl -fs "http://example.website.domain/$username/index.html") ... x=$(echo "$data" | wc -m) 来捕获来自set -o pipefail的错误):

curl

否则,如@Dominique所述,您的x=$(curl -fs "http://example.website.domain/$username/index.html" | wc -m) 将无限期等待直到获得一些输入。

答案 2 :(得分:0)

正如其他人已经指出的那样,只有#!/bin/bash filename=$1 # Use read -r while read -r username; do if page=$(curl -fs "http://example.website.domain/$username/index.html"); then # Feed the results from curl to wc x=$(wc -m <<<"$page") # Don't overwrite output file on every iteration echo "$username $x" else # Include parameter in error message; print to stderr echo "$0: The page for $username doesn't exist" >&2 fi # Note proper quoting # Collect all output redirection here, too done < "$filename" >output.txt 会“挂起”,因为它希望您在stdin上提供输入。

您似乎正在寻找类似的东西

CustomPreference