使用awk或sed命令循环从文件打印多个特定行

时间:2017-01-13 20:49:11

标签: bash awk

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

H3430
H3467
H9805

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

1
4
9
13
15

这些数字是我必须从file.txt中提取的行数(ID)。我需要生成另一个文件,newfile.txt让它调用它,只有390个ID在index.txt要求的特定行中(列表的第一个ID,第四个,第九个,等等)上)。

所以,我试着做以下循环,但它没有用。

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

我是一个关于这件事的菜鸟......所以,我需要一些帮助。即使它是我的循环或你建议的新解决方案。谢谢:))

3 个答案:

答案 0 :(得分:3)

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

$ seq 2500 > /tmp/2500

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

$ echo "1
4
9
13
15" > /tmp/390

您可以通过将行号读入数组并在该数组中打印行来打印文件2500中的行N:

$ 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 's/$/p/' /tmp/390 | sed -n -f - /tmp/2500,但这不适用于OS X: - (

你可以这样做:

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

答案 1 :(得分:2)

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

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

使用两个文件时,必须使用FNR,因为当新文件启动时它会重置为1(相反,NR将继续递增)。

Ed Morton在评论中表示。然后可以对该命令进行细化以进一步删除{print $1},因为awk默认打印真相。

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

答案 2 :(得分:0)

如果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

如果文件实际上没有排序,请使用sort:

快速排序
sort -n index.txt > temp.index.txt
rm index.txt
mv temp.index.txt index.txt