Bash - 按列加入(合并)文件
Bash - joining (merging) files by columns
文件中有三个列,分隔符为“|”,行中的列可能为空。我需要将第二个和第三个文件连接到第一个文件中的第 3 列和第 4 列,以及第二个和第三个文件中的第 1 列。
例如:
file1.txt:
123456||4|11|17|A||10|B|1
123457||4|11|17|A||12||1
123458||5|11|17|A||1|Б|1
123459||6|13|17|A||1|Б|1
file2.txt:
4|Forth
5|Fifth
6|Sixth
file3.txt:
11|st.|Eleventh
13|pr.|Thirteenth
我想要什么输出:
123456||4|Forth|11|st.|Eleventh|17|A||10|B|1
123457||4|Forth|11|st.|Eleventh|17|A||12||1
123458||5|Fifth|11|st.|Eleventh|17|A||1|Б|1
123459||6|Sixth|13|pr.|Thirteenth|17|A||1|Б|1
如何编写 Bash 脚本来满足我的需求?我知道这是 awt 命令,但我无法编写脚本。感谢您的回答。
您可以使用这个 awk 命令:
awk 'BEGIN{ FS=OFS="|" }
NR == FNR {a[]=[=10=]; next}
NR == FNR + length(a) {b[]=[=10=]; next}
{=b[]; =a[]} 1' file3.txt file2.txt file1.txt
123456||4|Forth|11|st.|Eleventh|17|A||10|B|1
123457||4|Forth|11|st.|Eleventh|17|A||12||1
123458||5|Fifth|11|st.|Eleventh|17|A||1|Б|1
123459||6|Sixth|13|pr.|Thirteenth|17|A||1|Б|1
解释:
BEGIN{ FS=OFS="|" }
- 将输入和输出字段分隔符设置为管道 |
NR == FNR
- 仅对第一个文件执行此块
a[]=[=14=]; next
- 创建一个数组a
,键为</code>,值为整行</li>
<li><code>NR == FNR + length(a)
- 仅对第二个文件执行此块
b[]=[=18=]; next
- 创建一个数组b
,键为</code>,值为整行</li>
<li>为最后一个(第 3 个)文件执行下一个块 <code>{...}
=b[];
- 将 b[]
的值分配给第 3 个字段
=a[];
- 将 a[]
的值分配给第 4 个字段
1
- 是打印每条记录的默认动作
这里是:
#!/bin/bash
while IFS='|' read c1 c2 c3 c4 c5 c6 c7 c8 c9 c10
do
st1=$( fgrep "$c3" file2.txt )
st2=$( fgrep "$c4" file3.txt )
echo "$c1|$c2|$st1|$st2|$c5|$c6|$c7|$c8|$c9|$c10"
done
假设文件已排序:
join -t'|' -1 4 -2 1 \
<(join -t '|' -1 3 -2 1 file1.txt file2.txt) file3.txt
如果您确实需要特定顺序的字段,请添加输出格式选项:
-o1.2,1.3,1.1,1.11,1.4,2.2,2.3,1.5,1.6,1.7,1.8,1.9,1.10,1.11
文件中有三个列,分隔符为“|”,行中的列可能为空。我需要将第二个和第三个文件连接到第一个文件中的第 3 列和第 4 列,以及第二个和第三个文件中的第 1 列。
例如:
file1.txt:
123456||4|11|17|A||10|B|1
123457||4|11|17|A||12||1
123458||5|11|17|A||1|Б|1
123459||6|13|17|A||1|Б|1
file2.txt:
4|Forth
5|Fifth
6|Sixth
file3.txt:
11|st.|Eleventh
13|pr.|Thirteenth
我想要什么输出:
123456||4|Forth|11|st.|Eleventh|17|A||10|B|1
123457||4|Forth|11|st.|Eleventh|17|A||12||1
123458||5|Fifth|11|st.|Eleventh|17|A||1|Б|1
123459||6|Sixth|13|pr.|Thirteenth|17|A||1|Б|1
如何编写 Bash 脚本来满足我的需求?我知道这是 awt 命令,但我无法编写脚本。感谢您的回答。
您可以使用这个 awk 命令:
awk 'BEGIN{ FS=OFS="|" }
NR == FNR {a[]=[=10=]; next}
NR == FNR + length(a) {b[]=[=10=]; next}
{=b[]; =a[]} 1' file3.txt file2.txt file1.txt
123456||4|Forth|11|st.|Eleventh|17|A||10|B|1
123457||4|Forth|11|st.|Eleventh|17|A||12||1
123458||5|Fifth|11|st.|Eleventh|17|A||1|Б|1
123459||6|Sixth|13|pr.|Thirteenth|17|A||1|Б|1
解释:
BEGIN{ FS=OFS="|" }
- 将输入和输出字段分隔符设置为管道|
NR == FNR
- 仅对第一个文件执行此块a[]=[=14=]; next
- 创建一个数组a
,键为</code>,值为整行</li> <li><code>NR == FNR + length(a)
- 仅对第二个文件执行此块b[]=[=18=]; next
- 创建一个数组b
,键为</code>,值为整行</li> <li>为最后一个(第 3 个)文件执行下一个块 <code>{...}
=b[];
- 将b[]
的值分配给第 3 个字段=a[];
- 将a[]
的值分配给第 4 个字段1
- 是打印每条记录的默认动作
这里是:
#!/bin/bash
while IFS='|' read c1 c2 c3 c4 c5 c6 c7 c8 c9 c10
do
st1=$( fgrep "$c3" file2.txt )
st2=$( fgrep "$c4" file3.txt )
echo "$c1|$c2|$st1|$st2|$c5|$c6|$c7|$c8|$c9|$c10"
done
假设文件已排序:
join -t'|' -1 4 -2 1 \
<(join -t '|' -1 3 -2 1 file1.txt file2.txt) file3.txt
如果您确实需要特定顺序的字段,请添加输出格式选项:
-o1.2,1.3,1.1,1.11,1.4,2.2,2.3,1.5,1.6,1.7,1.8,1.9,1.10,1.11