使用awk进行过滤将返回空文件

使用awk进行过滤将返回空文件,awk,Awk,我有一个与这个问题类似的问题: 上述问题答案中的解决方案对我不起作用 我有制表符分隔的txt文件(都在文件夹中)。对于每个文件,我想创建一个新文件,其中只包含列$9(medcodeid)中具有特定值的行。具体值可在medicalcode_list.txt中找到。 没有错误,但是它只返回空文件 代码列表 medcodeid 2576 3199 patid consid ... medcodeid 500470520002

我有一个与这个问题类似的问题:

上述问题答案中的解决方案对我不起作用

我有制表符分隔的txt文件(都在文件夹中)。对于每个文件,我想创建一个新文件,其中只包含列$9(medcodeid)中具有特定值的行。具体值可在medicalcode_list.txt中找到。 没有错误,但是它只返回空文件

代码列表

medcodeid   
2576        
3199    
patid           consid      ... medcodeid       
500470520002    3062539302  ... 2576    
503576720002    3062537720  ... 3199
输入文件的格式

patid           consid      ... medcodeid   
500470520002    3062539302  ... 2576    
951924020002    3062538414  ... 310803013       
503478020002    3061587464  ... 257619018       
951924020002    3062537807  ... 55627011        
503576720002    3062537720  ... 3199    
所需输出

medcodeid   
2576        
3199    
patid           consid      ... medcodeid       
500470520002    3062539302  ... 2576    
503576720002    3062537720  ... 3199
我的代码

mkdir HBA1C_observation_bypracid
awk '
    NR==FNR {mlist[$1]; next }
    FNR==1 {close(out); out="HBA1C_observation_bypracid/HBA1C_" FILENAME }
    ($9 in mlist) { print > out } 
' PATH/medicalcode_list.txt *.txt
解决方案

mkdir HBA1C_observation_bypracid
awk '
    BEGIN{ FS=OFS="\t" }
    NR==FNR {mlist[$1]; next }
    FNR==1 {close(out); out="HBA1C_observation_bypracid/HBA1C_" FILENAME }
    ($9 in mlist) { print > out } 
' PATH/medicalcode_list.txt *.txt

添加“开始…”解决了我的问题。

您可以使用
join
将两个文件合并到一列中

  • 文件必须在联接列上排序。要对列执行数字排序,请使用这种方式,其中
    N
    是列号:

      sort -kN -n FILE
    
  • 您还需要了解每个文件的第一行(列名)。您可以按以下方式使用tail命令,其中N是要从中输出内容的行数(因此第2行):

  • 。。。但仍需要显示列值:

    head -n 1 FILE
    
  • 要连接两个文件f1和f2,请在f1的c1字段和f2的c2字段以及文件x的输出字段y上执行以下操作:

    join -1 c1 -2 c2 f1 f2 -o "x.y, x.y"
    
工作样本:

head -n 1 input_file
for input_file in *.txt ; do
    join -1 1 -2 9 -o "2.1 2.2 2.3 2.4 2.5 2.6 2.7 2.8 2.9" \
         <(tail -n +2 PATH/medicalcode_list.txt | sort -k1 -n) \
         <(tail -n +2 "$input_file" | sort -k3 -n)
done


注意:列名与值不对齐。不知道这是不是先决条件。您可以使用
printf
命令格式化显示。

我个人认为,在shell中循环(理解这将多次重新读取代码列表)会更简单,使用更简单的awk函数,您应该能够测试和调试。比如:

用于*.txt中的文件;做
awk'FNR==NR{mlist[$1]}FNR!=NR&&(9美元)打印\
PATH/medicalcode_list.txt“$file”>HBA1C_观察\u bypracid/HBA1C_$file
完成
您应该能够在不重定向的情况下启动,以确保对于单个文件,您可以将结果打印到预期的终端。如果您不这样做,可能会有一些关于文件的错误假设

另一种选择是编写一个单独的awk脚本,将代码写入另一个awk脚本中的列表硬编码。还可以检查变量
mlist
的内容

printf'在mlist{print}中开始{\n%s\n}\n$9'\
“$(awk'{print“mlist[“$1”]”“}”路径/medicalcode_list.txt)”>filter.awk
对于*.txt格式的文件;做
awk-f filter.awk“$file”>HBA1C\u观察值\u bypracid/HBA1C\u“$file”
完成

不需要。我只需要最有效的方法,因为需要处理大量数据。如果您将$9替换为$NF,这会带来什么?您很可能在
代码列表
或输入文件中遇到
CRLF
行尾。这意味着您试图将
2576\r
2576
匹配,但这将不起作用。有关更多信息,请查看。您可以使用
cat-vET file
快速检查您的文件,以查看是否存在意外情况。或者更简单:只需键入
file filename
这将为您提供两个文件都是ASCI的信息。行尾显示为^I非常感谢您的想法。您的第一种方法产生了与我之前相同的输出:我得到了一个空的输出文件。“硬编码列表”如下所示:cat filter.awk BEGIN{mlist[medcodeid]mlist[2576]mlist[3199]}然而,awk-f filter.awk“$file”>HBA1C_observation\u bypracid/HBA1C_1;“$file”的输出是一个没有头的输出文件,源文件中有随机行,而不是基于此进行筛选的行,在我看来,你认为第9列与awk的想法不一样。我会从小处着手,只使用最简单的awk脚本来查看不同专栏中awk的真实想法。从
awk'{print$1}'
开始,然后是$2,等等。您还评论说行尾是
^I
。这会很奇怪,因为它通常表示一个制表符,这也是您所说的分隔符。正如另一位评论员所说的,您还需要确保有unix行结尾。谢谢!这是一个重要的暗示。您是对的-输入文件无法识别(制表位/空单元格被折叠)。如果我添加BEGIN{FS=OFS=“\t”},我的代码和您的代码都能完美工作。谢谢您的想法!这运行时没有错误,但是控制台中既没有任何输出文件也没有输出。我错过了什么?我也不确定过滤在代码中的具体位置。我刚刚开始使用awkI,但仍然无法运行此功能。然而,我找到了一个解决办法。我必须将BEGIN{FS=OFS=“\t”}添加到我的代码中。非常感谢您的努力!