真的需要你的帮助。我有一个文件,其中包含一行中的(字段:值)等数据
File.A
A:13 B:2 D:5 F:92 G:3 ...
我创建了一个包含" A到Z"。
的文件File.B
A B C D E F G H I J ...
尝试使用bash脚本获取内容并修复输出,该输出将插入带有0值的未命中行。
A:13 B:2 C:0 D:5 E:0 F:92 G:3 H:0 ...
想了两天......但是我的头脑里还没有发现。有什么办法可以解决吗?
答案 0 :(得分:7)
让我们进行大括号扩展工作:{A..Z}
扩展为所有字母列表:
$ echo {A..Z}
A B C D E F G H I J K L M N O P Q R S T U V W X Y Z
然后我们可以遍历所有行grep
。如果匹配,我们打印该行;否则,我们打印letter:0
。
for letter in {A..Z}
do
grep "^$letter" file || echo "$letter:0"
done
$ for letter in {A..Z}; do grep "^$letter" file || echo "$letter:0"; done
A:13
B:2
C:0
D:5
E:0
F:92
G:3
H:0
I:0
J:0
K:0
L:0
M:0
N:0
O:0
P:0
Q:0
R:0
S:0
T:0
U:0
V:0
W:0
X:0
Y:0
Z:0
现在您更新了问题并且输入文件包含同一行中的所有内容,您可以使用此grep来匹配:
grep -o "$word:[0-9]*" file
然后用空格替换新行:
$ for word in {A..Z}; do grep -o "$word:[0-9]*" file || echo "$word:0"; done | tr '\n' ' '
A:13 B:2 C:0 D:5 E:0 F:92 G:3 H:0 I:0 J:0 K:0 L:0 M:0 N:0 O:0 P:0 Q:0 R:0 S:0 T:0 U:0 V:0 W:0 X:0 Y:0 Z:0
答案 1 :(得分:2)
如果您喜欢awk
,可以试试这个:
awk -F: -vRS=" " '
{ c[$1] = $2 }
END{
for(i=65;i<91;++i){
a=sprintf("%c", i)
printf("%c:%d ",i,c[a])
}
}' A
其中A
是您的文件。第一个块构建一个已设置的所有值的数组。读取完所有文件后,循环将遍历A
(65)到Z
(90)的ascii值,并打印出已在数组中设置的值。缺少的那些打印为0
。
输出:
A:13 B:2 C:0 D:5 E:0 F:92 G:3 H:0 I:0 J:0 K:0 L:0 M:0 N:0 O:0 P:0 Q:0 R:0 S:0 T:0 U:0 V:0 W:0 X:0 Y:0 Z:0
由于每个人显然都无法从我的回答中得到足够的信息,所以这是另一种可以做到的方式,受到@fedorqui's answer中使用的{A..Z}
范围的启发:
awk -F: -vRS=" " '
NR==FNR { a[i++] = $1; next }
{ b[$1] = $2 }
END{for(i=0;i<length(a);++i)printf("%c:%d ",a[i],b[a[i]])}' - <<<$(echo {A..Z}) A
第一个块读入字母表中的所有字母,从而减少了解字符代码的需要。第二个块从您的文件A
构建一个数组。读取文件后,将打印出所有值,从而产生与上述相同的输出。
答案 2 :(得分:2)
Pure Bash,没有外部流程。如果在行中找到字母或字母后面的字母,则打印匹配,否则为0。
read content < "$infile"
for letter in {A..Z}; do
if [[ $content =~ ${letter}:[[:digit:]]+ ]] ; then
echo "${BASH_REMATCH[0]}"
else
echo "${letter}:0"
fi
done
或更短
for x in {A..Z}; do
[[ $content =~ ${x}:[0-9]+ ]] && echo "${BASH_REMATCH[0]}" || echo "${x}:0"
done