gpt4 book ai didi

linux - Bash循环只读最后一行

转载 作者:塔克拉玛干 更新时间:2023-11-03 01:54:36 24 4
gpt4 key购买 nike

我在尝试使用 while 循环和 awk 提取多行冒号后面的数据时遇到问题.

这是我的数据结构:

Identifiers:BioSample:SAMD00019077
Identifiers:BioSample:SAMD00019076
Identifiers:BioSample:SAMD00019075
Identifiers:BioSample:SAMD00019074
Identifiers:BioSample:SAMD00019073
Identifiers:BioSample:SAMD00019072
Identifiers:BioSample:SAMD00019071;SRA:DRS051563
Identifiers:BioSample:SAMD00019070;SRA:DRS051562
Identifiers:BioSample:SAMD00019069;SRA:DRS051561
...
Identifiers:BioSample:SAMD00019005;SRA:DRS051497
Identifiers:BioSample:SAMD00015713;SRA:DRS012785

我想要得到的是BioSample ID ,类似于 SAMD00019077 .

我试过的脚本:

  1. while read line ; do echo $line | awk -F':' '{print $3}' > 1.tmp2 ; done < 1.tmp
  2. for line in猫 1.tmp ; do echo $line | awk -F':' '{print $3}' > 1.tmp2 ; done
  3. for line in猫 1.tmp ; do echo $line | awk -F: '{print $3 > "1.tmp2"}' ; done

他们只给了Biosample ID最后一行:

$ while read line ; do echo $line | 
awk -F':' '{print $3}' > 1.tmp2 ; done < 1.tmp
$ head 1.tmp2
SAMD00015713;SRA

我阅读了此处的帖子,看起来我的问题与 stdin 有关, stdoutstderr .

bash read loop only reading first line of input variable

bash while loop read only one line

我试过的解决方案,它给出了 1 行的结果

$ exec 3<&1
$ exec 1<&2
$ while read line ; do echo $line |
awk -F':' '{print $3}' > 1.tmp2 ; done< 1.tmp
$ head 1.tmp2
SAMD00015713;SRA
$ exec 1<&3 3<&-

我也试过exec < 1.tmp将文件指向 stdin但它会导致错误。

我发现这些脚本对我来说效果很好。但我真的很想知道为什么我上面尝试的脚本失败了。

cat 1.tmp | awk -F: '{print $3}' | head

awk -F: '{print $3}' 1.tmp | head

最佳答案

首先,awk 具有循环遍历行的能力,字段分隔符可以是正则表达式。

因此,您的脚本可以简化为这种优化格式:

awk -F'[;:]' '{print $3}' 1.tmp > 1.tmp2

这是您可以使用的优化格式。

话虽如此,您可能想知道脚本中出了什么问题。

while read line ; do echo $line | awk -F':' '{print $3}' > 1.tmp2 ; done < 1.tmp
^ here

上面标记的>就是重定向操作符。它将命令的标准输出(在本例中为 awk)写入指定的文件。它不追加,而是覆盖。因此,在循环的每次迭代中,都会清除文件并将命令的输出写入其中。因此它只留下最后一个条目。

要解决这个问题,您可以使用附加重定向:>>>

while read line ; do echo $line | awk -F':' '{print $3}' >> 1.tmp2 ; done < 1.tmp

现在,有一个警告。如果文件原本不是空的怎么办?此循环将附加到文件,而不先清除文件。要解决此问题,您可以先使用以下命令清除文件:

>1.tmp2; while read line ; do echo $line | awk -F':' '{print $3}' >> 1.tmp2 ; done < 1.tmp

但是,如果我们确定循环产生的所有标准输出都需要进入文件,您可以简单地将重定向移出循环。这样,shell 就不必一直打开和关闭文件描述符。

while read line ; do echo $line | awk -F':' '{print $3}'; done < 1.tmp > 1.tmp2

请注意,这些选项未经优化,但仍然有效。优化的选项是让 awk 本身按照答案的第一个片段中提到的那样进行逐行处理。

关于linux - Bash循环只读最后一行,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/57423117/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com