如果在另一个文件中找不到第 9-14 列中的字符,则从输出文件中排除行

如果在另一个文件中找不到第 9-14 列中的字符,则从输出文件中排除行

我有两个以列分隔的文件,我需要创建两个新文件,其中仅包含在两个文件中找到事务标识符的记录。标识符位于从第 9 列到第 14 列的字段中,但每个文件中的每条记录在 9-14 范围之前和之后都有唯一的数据,并且需要将可变数据转移到输出文件。每个标识符都保证出现一次或根本不出现。

我可以用 python 脚本来编写自己的脚本,但我没有看到太多对库中列分隔文件的本机支持,我觉得任何 *nix 系统(我在 Ubuntu 20.04 上)都应该有命令行实用程序专为以前的计算时代而构建,可以简单地处理这个问题。当然,如果该工具太陈旧,那么我会自己编写一个 python 脚本(除非您知道一个处理我没有看到的列分隔文件的包)。

感谢您的帮助。


示例:在每个文件中都找到包含第 9-14 列中的字符的一行ID:525,因此这些行将写入各自的输出文件中。两个输入文件都有在另一个文件中找不到的记录。

输入文件1.txt

Record1 ID:525 DATA A
Record2 ID:232 DATA B
Record3 ID:811 DATA C
Record4 ID:400 DATA D

输入文件2.txt

Record1 ID:448 DATA E
Record2 ID:525 DATA F

输出文件1.txt

Record1 ID:525 DATA A

输出文件2.txt

Record2 ID:525 DATA F

答案1

GNU awk(又名)可在 Ubuntu 20.04 上使用,并且可以通过其变量gawk处理固定宽度数据。FIELDWIDTHS

前任。最简单地说,给定

$ cat input_file1.txt
Record1 ID:525 DATA A
Record2 ID:232 DATA B
Record3 ID:811 DATA C
Record4 ID:400 DATA D

然后

$ gawk 'BEGIN{FIELDWIDTHS="8 6 *"} {print $2}' input_file1.txt
ID:525
ID:232
ID:811
ID:400

基于此,你可以做类似的事情

$ gawk '
  BEGIN {FIELDWIDTHS = "8 6 *"}
  BEGINFILE {outfile[ARGIND] = gensub("input","output","1",FILENAME)}
  NR==FNR {a[$2] = $0; next}
  ($2 in a){
    print a[$2] > outfile[1]
    print $0    > outfile[2]
  }
' input_file1.txt input_file2.txt

给予

$ head output_file?.txt
==> output_file1.txt <==
Record1 ID:525 DATA A

==> output_file2.txt <==
Record2 ID:525 DATA F

参见示例GNU Awk 用户指南:4.6 读取固定宽度数据

答案2

如果将每一行设置为字符串变量,则可以像这样检查第 9-14 列

myLine="Record1 ID:525 DATA A"
echo ${myLine:8:6}

${myLine:8:6}从第 9 列开始(8+1,因为索引从 0 开始)并向前移动 6 个字符。

之后,您只需在每个文件中执行检查(可能使用 grep)


您甚至可以使用 awk 获取第二列(字符集,以空格分隔)并对其他文件执行检查。

在我的脑海中(没有测试过)你可以做如下的事情:

#!/bin/bash
// This is based on the example you gave, only using 2 input files

files=("input_file1.txt" "input_file2.txt")

out_baseName="output_file"
index=1
adder=1
for file in ${files[@]}; do
    for line in $(cat $file); do
        id_string=`echo $line | awk '{ print $2 }'` // gets the 2nd column "ID:525"

        for subfile in ${files[@]}; do
            if [ "$subfile" == "$file" ]; then
                continue
            fi
            
            if grep "$id_string" $subfile; then
               echo $line >> ${out_baseName}${index}.txt
               grep "$id_string" $subfile >> ${out_baseName}$(($index+$adder)).txt
               
               index=$(($index+1))
               adder=$(($adder-1))
            fi
        done
    done
done


答案3

第一种方法1:

作为检查的示例输入,我们可以通过考虑第 2 列来做到这一点

awk 'NR==FNR{a[$2];next}($2 in a){print $0}' inputfile1.txt inputfile2.txt  >output_file2.txt

awk 'NR==FNR{a[$2];next}($2 in a){print $0}' inputfile2.txt inputfile1.txt  >output_file1.txt

第二种方法:

awk 'NR==FNR{a[substr($0,9,6)];next}(substr($0,9,6) in a){print $0}' inputfile2.txt inputfile1.txt >output_file1.txt

awk 'NR==FNR{a[substr($0,9,6)];next}(substr($0,9,6) in a){print $0}' inputfile1.txt inputfile2.txt  >output_file2.txt

输出

cat output_file1.txt 
Record1 ID:525 DATA A

cat output_file2.txt 
Record2 ID:525 DATA F

相关内容