File1
有固定长度的数字,每行一个数字:
1234
5678
1345
File2
包含“key=value”格式的数据字段:
abc:def=1999,xyz=1234;
abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;
我需要获取字段与 中的任何数字匹配的那些行File2
,def
但File1
该xyz
字段在模式匹配时被忽略。所以,我的结果应该是这样的:
abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;
答案1
我总是忘记大多数awk
命令,这对我的老大脑来说太多了,所以我提供了一个sed
替代方案
sed '/^[0-9]*$/H;G;/def=\([0-9]*\),.*\n\1/P;d' file1 file2
这个想法是收集保留空间中的数字file1
并使用反向引用来识别 file2 中包含以下数字的那些行:def=
- 该模式
^[0-9]*$
匹配仅包含数字的行,这些行是file1
行,我们将其附加到H
旧空间 G
将保留空间附加到模式空间,因此我们拥有模式空间中file2
的行和所有数字file1
- 该模式寻址在换行符之后重复
/def=\([0-9]*\),.*\n\1
后面的数字(反向引用)的所有行(因此它是保留空间集合的一部分)。打印那些没有附加内容的行def=
\1
P
d
抑制进一步的输出。你可以使用选项-n
代替
更新:视觉解释
正如埃德指出的那样,我的解释显然对每个人都没有帮助。如果您更像是一个“视觉思考者”,我将尝试说明其中的原理。请记住,这sed
不是编程工具,而更像是一个带有以下功能的自动文本编辑器保留空间作为“剪贴板”,而行被读入模式空间,工作完成的地方。
现在我按照建议在H
和G
命令后显示两个空格:
模式空间 | 保留空间 | 评论 |
---|---|---|
1234 |
1234 |
附加H 到(空)保留空间并嵌入换行符 |
1234 1234 |
1234 |
追加G 回模式空间,添加另一个换行符 |
5678 |
1234 5678 |
读取下一行时保留保留空间,因此下一行H 会附加下一个数字 |
5678 1234 5678 |
1234 5678 |
再次追加回模式空间,但仍然与def= 模式不匹配 |
file1 为了便于阅读,跳过第三行 |
||
abc:def=1999,xyz=1234; |
1234 5678 |
与模式不匹配^[0-9]*$ ,因此H 不执行 |
abc:def=1999,xyz=1234; 1234 5678 |
1234 5678 |
但G 被执行 |
P
现在看看如何应用命令的地址模式(\n
用作换行符的占位符):
abc:def=1999,xyz=1234;\n\n1234\n5678
def=####, .* #### stands for `[0-9]*`, but the back reference
as `\1` is not found: no match
abc:def=5678,xyz=1234;\n\n1234\n5678
def=####, .* \n#### here, the match is repeated as `\1`,so we know
the `def` number has been listed in `file1`
答案2
将数字收集到散列中(nums
在本例中),并使用它来方便以后查找:
awk -F '[=,;]' 'FNR==NR { nums[$1]; next } $2 in nums' file1 file2
输出:
abc:def=5678,xyz=1234;
abc:def=1234,xyz=5678;
如果字段的顺序不是恒定的,则可以使用以下方法:
awk -F'[=,;:]' '
FNR==NR { nums[$1]; next }
$2 == "def" && ($3 in nums) || $4 == "def" && ($5 in nums)
' file1 file2
答案3
grep -f <(sed 's/^/abc:def=/' file1.txt) file2.txt
或者,如果您的 shell 不支持,您可以创建一个新文件<()
:
sed 's/^/abc:def=/' file1.txt > patterns.txt
grep -f patterns.txt file2.txt
或者您可以创建一个 fifo 文件:
mkfifo fifo
sed 's/^/abc:def=/' file1.txt >fifo &
grep -f fifo file2.txt