我有两个示例文件,如下所示:
item name="NY" block="A" idnum="12345"
item name="NJ" block="B" idnum="123456"
item name="CT" block="C" idnum="1234567"
ID_B|ID_C|NY|4|8198|10|2374|127
ID_C|ID_D|NJ|4|8198|10|2374|127
ID_D|ID_E|CT|4|8198|10|2374|127
我希望能够生成一个文件作为参数传递ID,输出应该如下所示
如果我正在寻找ID_B
的信息,那么输出应为
ID_B|ID_C|NY|4|8198|10|2374|127 => "NY" block="A" idnum="12345"
如果我一起寻找两个ID_C
和ID_D
,那么它应该是
ID_C|ID_D|NJ|4|8198|10|2374|127 => "NJ" block="B" idnum="123456"
ID_D|ID_E|CT|4|8198|10|2374|127 => "CT" block="C" idnum="1234567"
答案 0 :(得分:2)
像
这样的东西echo "Please enter the key"
read key
grep "item name=\"$(grep "^${key}|" file2 | cut -d"|" -f3)\"" file1
编辑: 我没有做文字输出,只是想表明你可以grep字段。完整的解决方案应如下所示:
#!/bin/bash
if [ $# -eq 0 ]; then
echo "Usage $0 id [id2 ..]"
exit 1
fi
for key in $*; do
f2=$(grep "^${key}|" file2 )
f1=$(grep "item name=\"$(echo "^${f2}" | cut -d"|" -f3)\"" file1 )
echo "${f2} => ${f1#item name=}"
done
答案 1 :(得分:2)
使用bash,join,sort和awk。
script.sh:
#!/bin/bash
file1="File1"
file2="File2"
grep -f <(printf "^%s|\n" "$@") <(join -t '|' -1 1 -2 3 <(awk -F'"' '{OFS="|"; print $2,$4,$6}' "$file1" | sort -t '|' -k 1,1) <(sort -t '|' -k 3,3 "$file2") -o 2.1,2.2,2.3,2.4,2.5,2.6,2.7,2.8,2.3,1.2,1.3 | awk -F'|' '{ printf "%s|%s|%s|%s|%s|%s|%s|%s => \"%s\" block=\"%s\" idnum=\"%s\"\n",$1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11 }')
示例:script.sh ID_C ID_D
输出:
ID_D|ID_E|CT|4|8198|10|2374|127 => "CT" block="C" idnum="1234567" ID_C|ID_D|NJ|4|8198|10|2374|127 => "NJ" block="B" idnum="123456"
答案 2 :(得分:1)
awk,包裹在一个瘦的shell脚本中
#!/bin/sh
awk -F '[|"]' -v OFS='"' -v keys="$*" '
BEGIN {
n = split(keys, a, " ")
for (i=1; i <= n; i++) key[a[i]] = 1
}
NR == FNR {
if ($1 in key) line[$3] = $0
next
}
$2 in line {
$1 = line[$2] " => "
print
}
' file2 file1
然后
$ sh script.sh ID_B ID_D
ID_B|ID_C|NY|4|8198|10|2374|127 => "NY" block="A" idnum="12345"
ID_D|ID_E|CT|4|8198|10|2374|127 => "CT" block="C" idnum="1234567"
答案 3 :(得分:0)
你想要什么,与SQL中的JOIN非常相似。
不幸的是,在bash,awk或sed等过程语言中实现它需要字典或字符串索引字符串数组。 (即使使用它们,它也会像单行sql查询一样复杂得多。)它们都不支持它,尽管有很多可能模仿它。
在你的位置我会使用perl或python来解决这个问题 - 在这些语言上你的目标就是如此简单,即使有额外的学习努力,它也会像bash一样有效。
但是你想要一个bash-awk-sed解决方案,所以这就是我现在给你的。
不要单独使用这些语言,请将它们集成使用。在bash中你可以做的最简单的事情是使用外部命令grep
。
例如,一个集成的awk / bash核心部分完成了你的任务(我没有对它进行过测试):
awk 'BEGIN {FS="[_|]"} { print $2 " " $0}' file1|while read l
do
set $l
echo $2 $(grep 'block="'$1'"' file2)
done
但是要理解这段代码,调试它并扩展它,你需要有一个regexp的经验,转义的确切细节,以及如何将它们集成到这两种语言上是最快的。在我看来,如果你正在学习编程,那么在你开始学习perl / python之前它是必须的,但在日常工作中,更高级别的解决方案更好。
答案 4 :(得分:0)
您还可以编写一个简短的bash脚本,以蛮力的方式检索信息:
#!/bin/bash
[ -z "$1" -o -z "$2" -o -z "$3" ] && {
printf "error: insufficient input. Usage: %s file1 file2 query\n" ${0##*/}
exit 1
}
file1="$1"
file2="$2"
query="$3"
## line from file1
f1=$(grep "$query" "$file1")
[ -z "$f1" ] && {
printf "error: '%s' not found in '%s'\n." "$query" "$file1"
exit 1
}
## line from file2
f2=$(grep $(awk -F '|' '{ print $3 }' <<<$f1) "$file2")
[ -z "$f1" ] && {
printf "error: no related row found in '%s'\n." "$file2"
exit 1
}
printf "%s => %s\n" "$f1" "$f2"
<强>实施例强>
$ bash joinfiles.sh join1.txt join2.txt ID_B
ID_B|ID_C|NY|4|8198|10|2374|127 => item name="NY" block="A" idnum="12345"
$ bash joinfiles.sh join1.txt join2.txt ID_E
ID_D|ID_E|CT|4|8198|10|2374|127 => item name="CT" block="C" idnum="1234567"
$ bash joinfiles.sh join1.txt join2.txt ID_F
error: 'ID_F' not found in 'join1.txt'
处理多个输入标记
通过小幅调整,您可以轻松处理任意数量的标签。下面,代码将匹配作为参数3及更高版本提供的所有标记。如果您希望一次提供多个半打瞌睡的标签,那么您应该调整脚本以从stdin
读取标签,而不是将它们作为参数。另请注意,代码与第一个文件的第一个字段中的标记匹配。如果要匹配文件一中所有字段中的标记,则f1
将成为一个数组,代码的其余部分将对f1
中的每个元素进行操作。让我知道你在想什么。以下是多个输入标记作为参数的示例:
#!/bin/bash
[ -z "$1" -o -z "$2" -o -z "$3" ] && {
printf "error: insufficient input. Usage: %s file1 file2 query\n" ${0##*/}
exit 1
}
[ -f "$1" -a -f "$2" ] || {
printf "error: file not found. '%s' or '%s'\n" "$1" "$2"
exit 1
}
file1="$1"
file2="$2"
for i in "${@:3}"; do
query="$i"
## line from file1
f1=$(grep "^$query" "$file1")
[ -z "$f1" ] && {
printf "error: '%s' not found in '%s'\n." "$query" "$file1"
exit 1
}
## line from file2
f2=$(grep $(awk -F '|' '{ print $3 }' <<<$f1) "$file2")
[ -z "$f1" ] && {
printf "error: no related row found in '%s'\n." "$file2"
exit 1
}
printf "%s => %s\n" "$f1" "$f2"
done
使用/输出强>
$ bash joinfiles2.sh join1.txt join2.txt ID_B ID_D ID_F
ID_B|ID_C|NY|4|8198|10|2374|127 => item name="NY" block="A" idnum="12345"
ID_D|ID_E|CT|4|8198|10|2374|127 => item name="CT" block="C" idnum="1234567"
error: 'ID_F' not found in 'join1.txt'