Bash 使用awk或sed命令循环打印文件中的许多特定行

Bash 使用awk或sed命令循环打印文件中的许多特定行,bash,awk,Bash,Awk,我有一个带有ID名的大txt文件。它有2500行,一列。我们称之为file.txt H3430 H3467 H9805 另外,我还有另一个文件index.txt,它有390个数字: 1 4 9 13 15 这些数字是我必须从file.txt中提取的ID行数。我需要生成另一个文件newfile.txt,我们称之为newfile.txt,其中只有特定行中的390个ID,index.txt要求列表的第一个ID、第四个ID、第九个ID,依此类推 所以,我试着做下面的循环,但没有成功 num=$'in

我有一个带有ID名的大txt文件。它有2500行,一列。我们称之为file.txt

H3430
H3467
H9805
另外,我还有另一个文件index.txt,它有390个数字:

1
4
9
13
15
这些数字是我必须从file.txt中提取的ID行数。我需要生成另一个文件newfile.txt,我们称之为newfile.txt,其中只有特定行中的390个ID,index.txt要求列表的第一个ID、第四个ID、第九个ID,依此类推

所以,我试着做下面的循环,但没有成功

num=$'index.txt'
for i in num
do
awk 'NR==i' "file.txt" > newfile.txt
done

在这件事上我是个笨蛋。。。所以,我需要一些帮助。即使是使用我的循环或您建议的新解决方案。谢谢:

您可以将index.txt文件读入地图,然后将其与file.txt的行号进行比较。将输出重定向到另一个文件

awk 'NR==FNR{line[$1]; next}(FNR in line){print $1}' index.txt file.txt > newfile.txt
当您处理两个文件时,需要使用FNR,因为当新文件开始时,FNR将重置为1,反之,NR将继续增加

正如埃德·莫顿在评论中所暗示的那样。然后可以对该命令进行优化,以进一步删除{print$1},因为awk默认在truth上打印

awk 'NR==FNR{line[$1]; next} FNR in line' index.txt file.txt > newfile.txt

您可以将index.txt文件读入地图,然后将其与file.txt的行号进行比较。将输出重定向到另一个文件

awk 'NR==FNR{line[$1]; next}(FNR in line){print $1}' index.txt file.txt > newfile.txt
当您处理两个文件时,需要使用FNR,因为当新文件开始时,FNR将重置为1,反之,NR将继续增加

正如埃德·莫顿在评论中所暗示的那样。然后可以对该命令进行优化,以进一步删除{print$1},因为awk默认在truth上打印

awk 'NR==FNR{line[$1]; next} FNR in line' index.txt file.txt > newfile.txt

让我们创建一个示例文件,用seq模拟2500行文件:

并使用您的示例在名为390的文件中打印行号:

$ echo "1
4
9
13
15" > /tmp/390
通过将行号读入数组并打印该数组中的行(如果在该数组中):

$ awk 'NR==FNR{ a[$1]++; next} a[FNR]' /tmp/390 /tmp/2500
您还可以使用sed命令文件:

$ sed 's/$/p/' /tmp/390 > /tmp/sed_cmd
$ sed -n -f /tmp/sed_cmd /tmp/2500
使用GNU sed,您可以执行sed的/$/p/'/tmp/390 | sed-n-f-/tmp/2500,但这在OS X上不起作用:-

您可以通过以下方法执行此操作:

$ sed -n -f <(sed 's/$/p/' /tmp/390) /tmp/2500

让我们创建一个示例文件,用seq模拟2500行文件:

并使用您的示例在名为390的文件中打印行号:

$ echo "1
4
9
13
15" > /tmp/390
通过将行号读入数组并打印该数组中的行(如果在该数组中):

$ awk 'NR==FNR{ a[$1]++; next} a[FNR]' /tmp/390 /tmp/2500
您还可以使用sed命令文件:

$ sed 's/$/p/' /tmp/390 > /tmp/sed_cmd
$ sed -n -f /tmp/sed_cmd /tmp/2500
使用GNU sed,您可以执行sed的/$/p/'/tmp/390 | sed-n-f-/tmp/2500,但这在OS X上不起作用:-

您可以通过以下方法执行此操作:

$ sed -n -f <(sed 's/$/p/' /tmp/390) /tmp/2500
如果index.txt被排序,我们可以按顺序遍历file.txt。 这将操作的数量减少到了最快脚本的最小值:

awk 'BEGIN
     {  indexfile="index.txt"
        if ( (getline ind < indexfile) <= 0)
             { printf("Empty %s\n; exiting",indexfile);exit }
     }
     {  if ( FNR <  ind ) next
        if ( FNR == ind ) printf("%s %s\n",ind,$0)
        if ( (getline ind < indexfile) <= 0) {exit}
     }' file.txt
如果index.txt被排序,我们可以按顺序遍历file.txt。 这将操作的数量减少到了最快脚本的最小值:

awk 'BEGIN
     {  indexfile="index.txt"
        if ( (getline ind < indexfile) <= 0)
             { printf("Empty %s\n; exiting",indexfile);exit }
     }
     {  if ( FNR <  ind ) next
        if ( FNR == ind ) printf("%s %s\n",ind,$0)
        if ( (getline ind < indexfile) <= 0) {exit}
     }' file.txt

欢迎来到堆栈溢出!看起来你在请求家庭作业帮助。虽然我们对此本身没有问题,但请注意这些,并相应地编辑您的问题。这不是家庭作业帮助。我是一名生物学家,试图在这些主题上进一步学习,因为我想。我是在分析过程中生成这些文件的,但有时我会被卡住,因为我不是计算机科学领域的人。如果说“家庭作业”是因为我教的是一个说教式的人,我试图说清楚。但我明白你的意思。无论如何谢谢欢迎来到Stack Overflow!看起来你在请求家庭作业帮助。虽然我们对此本身没有问题,但请注意这些,并相应地编辑您的问题。这不是家庭作业帮助。我是一名生物学家,试图在这些主题上进一步学习,因为我想。我是在分析过程中生成这些文件的,但有时我会被卡住,因为我不是计算机科学领域的人。如果说“家庭作业”是因为我教的是一个说教式的人,我试图说清楚。但我明白你的意思。不管怎样,谢谢你,它成功了!!!非常感谢你!但请记住,我是新来的。。。。什么是FNR?读入地图是什么意思?如果你能解释一下,那就太好了。我想了解它:@MelNuesch数组在awk中本质上是关联的。索引是字符串。它们在Python中也称为dictionary,在Java中称为HashMap。FNR是一个内置的awk变量,它记住当前文件的行号。我会建议抓取,这将解释更详细的awk。它的工作!!!非常感谢你!但请记住,我是新来的。。。。什么是FNR?读入地图是什么意思?如果你能解释一下,那就太好了。我想了解它:@MelNuesch数组在awk中本质上是关联的。索引是字符串。它们在Python中也称为dictionary,在Java中称为HashMap。FNR是一个内置的awk变量,它记住当前文件的行号。我建议抓取,这将更详细地解释awk。用sed创建一个脚本以提供给sed是一种奇怪的美化
这是一个扭曲思想的标志。喜欢。是的,自举很酷。不幸的是,当生成的脚本变大时,它会失败,当您从文件中选择行时,一次执行一个命令,很容易达到这个限制。我想大概有一千行左右的命令是它可以使用的,但是它可能取决于每个命令的长度,对于不同的sed变体,idk可能会有所不同。awk命令OTOH将在所有系统上的所有awk上稳定、高效、可移植地工作,以获取大量文件。使用sed创建脚本以提供给sed是一种奇异的美丽,也是一种扭曲思维的标志。喜欢。是的,自举很酷。不幸的是,当生成的脚本变大时,它会失败,当您从文件中选择行时,一次执行一个命令,很容易达到这个限制。我想大概有一千行左右的命令是它可以使用的,但是它可能取决于每个命令的长度,对于不同的sed变体,idk可能会有所不同。awk命令OTOH将在所有系统上的所有awk上以健壮、高效和可移植的方式工作,以获取大量文件。