【问题标题】:Why does "cut" command skip first line in this "while read line" loop?为什么“cut”命令在这个“while read line”循环中跳过第一行?
【发布时间】:2021-05-19 20:24:47
【问题描述】:

我正在编写一个 bash 脚本,我需要获取文件中每一行的第二个字段,并将它们保存在另一个文件中。我知道有很多可能的方法可以做到这一点,但是,我首先尝试使用while read line; do,但我被卡住了。现在,我真的很想知道发生了什么。 例如,输入文件是:

line1   11111
line2   222222
line3   333
line4   4444

(字段分隔符为“\t”)。

这就是我正在做的:

inputfile=$1
cat $"inputfile" | while read -r line
    do
    cut -f2 >> results_file
    done

问题是,输出将是:

222222
333
4444 

(跳过第一行)

我已经测试了数百个修改,并尝试使用其他命令而不是 cut(例如,sedgrep...)。我会很感激一些帮助,或者有人指出我正确的方向。 非常感谢!

【问题讨论】:

  • 尝试用dos2unix转换你的文件我以为你的文件是windows换行格式
  • 您可以使用 echo 打印每一行,例如while read -r line; do echo "$line" | cut -d$'\t' -f2; done < input.txt > results.txt 或者你可以只使用 awk 例如awk '{print $2}' input.txt > results.txt。有很多方法可以做您想做的事 - 也许更多信息会帮助我们为您提供帮助
  • 问题是,我需要一个循环,因为我输入的字段 2 实际上是 URL:我必须在列中生成一个包含此输入的字段 1 的文件,并从其下载特定信息另一列中的相应 URL。为了知道每个原始 URL 对应的是哪个下载的文件,我认为最好直接用循环来完成。我希望我能很好地解释自己......另外,我已经按照你的建议做了,但是在 de 选项 cut -d$'\t' 中没有 de "$"。这是否意味着使用“\ t at the end”作为分隔符?顺便说一句,它完美地工作。非常感谢。

标签: bash


【解决方案1】:

您没有使用由read 设置的变量$line。试试吧

inputfile=$1
cat "$inputfile" | while read -r line
    do
    echo "$line" | cut -f2 >> results_file
    done

在您的原始代码中,while 循环实际上只运行一次,而不是四次;尝试将echo 'Hello!' 放入原始代码的循环中。您只会看到一次消息,而不是四次。我猜,没有echo "$line" | 部分,cut -f2 ... 部分会消耗掉管道。

也就是说,您的while 循环首先使用标准输入的第一行并将这一行放入变量$line 中,留下接下来的三行供以后使用。但从未使用过$line。相反,其余三行由命令cut 使用。

命令组中的所有命令都在应用于命令组(或任何复合命令)的任何重定向范围内:

——https://mywiki.wooledge.org/BashGuide/CompoundCommands

管道操作符为每个命令创建一个子shell环境。

——https://mywiki.wooledge.org/BashGuide/InputAndOutput

我们可以将引号解释为“您的 while 循环的标准输入(即 cat "$inputfile" 的输出)由 cut 访问,除非您通过创建新的子外壳(例如,通过另一个管道 @987654336)切断其访问权限@。”

顺便说一句,您可以只使用 cut -f2 "$inputfile" >> results_file 而不使用 while 循环。

【讨论】:

    【解决方案2】:

    关于您的评论Does it mean to use "\t at the end" as a separator - 不。你混淆了$'\t''\t$' 的建议。 $'\t' 表示“从转义序列\t 生成的文字制表符”。

    您还在评论中说,您真正的第二个字段是要卷曲的 URL。无论如何,您都不应该使用 UUOC 并进行切割,以下是真正做到这一点的方法:

    while IFS=$'\t' read -r key url; do
        val=$(curl "$url" | whatever)
        printf '%s\t%s\n' "$key" "$val"
    done < "$inputfile" > results_file
    

    whatever 替换为您用于从curl 输出中生成所需输出的任何命令。

    【讨论】:

    • 非常感谢,我会用的!
    猜你喜欢
    • 1970-01-01
    • 2019-11-08
    • 2011-09-08
    • 2012-08-30
    • 1970-01-01
    • 2017-09-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多