我有一个如下所示的文件作为示例:
B01 112178282 A01 112178282
A05 44887670 A01 44887670
B01 114451441 A01 114451441
B10 8364597 A01 8364597
B01 123453906 A01 123453906
A05 9155966 A01 9155966
A05 86420950 A01 86420950
A10 75684694 A01 75684694
A04 71261964 A01 71261964
B01 1262441 A01 1262441
B01 471272 A01 471272
B01 17007 A01 17007
A04 115637044 A01 115637044
A07 9376758 A01 9376758
我想要两个单独的输出文件
- 什么时候
num val in col1 == num val in col3
- 第二个输出文件 当
num val in col 1 != num val in col 3
例如,col1 是 B01,col3 是 A01,这里两列中的数字部分是相同的01
。现在,所有这些条件都应列在 file1 中。
如果 col1 是 A05,col3 是 A01,两列中的数字部分不同07 != 01
,那么这些应该列在另一个文件中2
答案1
awk 'substr($1,2)==substr($3,2) { print $0 > "file1" } substr($1,2) != substr($3,2) { print $0 > "file2" }' masterfile
使用包含原始数据的 masterfile 并使用 awk 的 substr 函数,我们忽略第一个和第三个空格分隔字段的第一个字母,留下要比较的数字。然后,我们对这些数字执行条件检查,将它们相应地放入特定文件(文件 1 和文件 2)中。
答案2
使用awk
会产生两个文件;第 1列和第 3列的数字部分相同的行将放入单独的文件中,而这些列不同的行将放入另一个文件中。
awk -F"[A B]" '{
print >(($2==$5)?"matches.txt":"non_matches.txt")
}' infile.txt
这会将 awk 的字段分隔符设置为A
,B
或空格字符集,然后进行比较,如果数字部分相同则当前行将写入“matches.txt”文件,否则它将写入“non_matches.txt”文件。
答案3
perl -alMFatal=open -pe '
BEGIN{ unlink, open *{+uc}, ">>$_" for qw/file1.log file2.log/; }
select $F[0] =~ s/^\D*//r eq $F[2] =~ s/^\D*//r ? *{"FILE1.LOG"} : *{"FILE2.LOG"};
' sample.txt
解释
Perl
选项:-a
将根据空格将行拆分为字段,这些字段可通过$F[0] $F[1] ...
-l
将设置RS
为换行符和ORS
换行符。-M
将加载模块并包含其名称空间中的Fatal.pm
函数。open
这意味着主代码中打开文件时出现的任何错误都会消失。-p
将逐行读取sample.txt 文件,并在应用所有转换后启用自动打印行。
- 该
BEGIN
块应删除任何现有的 file1.log 和 file2.log 并以append
文件模式打开文件句柄。 select
命令选择要在其上打印当前行的文件句柄。$F[0] =~ s/^\D*//r
应去除第一个字段中的任何前导非数字(假设所有数字都放置在该字段的末尾)。- 我们对第三个字段 ($F[2]) 执行类似的操作,然后以字符串格式比较这些结果(而不是数字,因为数字中 001 = 1)。当字符串匹配时,我们选择文件句柄 *FILE1.LOG,这意味着由于该
-p
选项,当前行将打印在此处。 OTW,文件句柄 *FILE2.LOG 被设置为默认句柄,并且-p
选项使得Perl
在此处打印当前行。
我们可以使用sed
如图所示的工具执行相同的操作:(假设 GNU sed)
sed -Ee '
h;s/\S+/\n&\n/3
/^[^0-9[:blank:]]*([0-9]+).*\n(.*[^0-9])?\1\n/{
g
s/^//w file1.log
d
}
g
' < sample.txt > file2.log
- 在第一步中,我们通过标记将第三个字段括起来。
- 然后,我们对第一个字段的尾随部分中的数字进行比较,以与第三个字段的尾随部分中的数字相匹配。
- 在匹配时,我们调用存储当前行(不含标记)的保留空间,并将其附加到 file1.log 文件中。
- 如果没有匹配,我们调用保留空间并将其发送到 stdout,并由 shell 将其存储在 file2.log 文件中。
答案4
将 GNUsed
与编辑脚本一起使用(调整sed
第一行 GNU 的路径和名称以匹配您的系统):
#!/usr/bin/sed -nrf
/^[A-Z]([0-9]+) [0-9]+ [A-Z]\1 [0-9]+$/{
w match.txt
b
}
w nonmatch.txt
在示例文件上运行此命令将生成两个结果文件match.txt
和nonmatch.txt
:
$ chmod +x script.sed
$ ./script.sed file.in
$ cat match.txt
B01 112178282 A01 112178282
B01 114451441 A01 114451441
B01 123453906 A01 123453906
B01 1262441 A01 1262441
B01 471272 A01 471272
B01 17007 A01 17007
$ cat nonmatch.txt
A05 44887670 A01 44887670
B10 8364597 A01 8364597
A05 9155966 A01 9155966
A05 86420950 A01 86420950
A10 75684694 A01 75684694
A04 71261964 A01 71261964
A04 115637044 A01 115637044
A07 9376758 A01 9376758
该脚本基本上尝试在每一行上匹配特定的正则表达式。如果第 1 列和第 3 列中的两个数字相同,则表达式匹配(我在这里使用反向引用来执行此操作,这就是 BSDsed
无法运行此脚本的原因)。
如果两个数字相等,则写入该行match.txt
,并且脚本分支到开头并继续下一行输入。
如果该行与正则表达式不匹配,它将被写入nonmatch.txt
.