0

我有两个文件。一个包含动物名称:

martin@potato:~$ cat animals.txt 
98 white elefant
103 brown dog
111 yellow cat
138 blue whale
987 pink pig
martin@potato:~$

..and other 包含他们居住的地方:

martin@potato:~$ cat places.txt 
98 safari
99
103 home
105
109
111 flat
138 ocean
500
987 farm
989
martin@potato:~$ 

动物.txt 中动物名称前的数字指向正确的位置。输出应该是这样的:

martin@potato:~$ ./animals.sh
safari  white elefant
home    brown dog
flat    yellow cat
ocean   blue whale
farm    pink pig
martin@potato:~$ 

bash 中将动物名称与位置映射的最优雅的解决方案是什么?

我是这样做的:

#!/usr/bin/env bash

#content of animals.txt file is stored into "$animals" variable using command substitution
animals=$(<animals.txt)

#content of places.txt file is stored into "$places" variable using command substitution
places=$(<places.txt)


#read(bash builtin) reads "$animals" variable line by line
while read line; do

    #"$animals_number" variable contains number in the beginning of the line; for example "98" in case of first line
    animals_number=$(echo "$line" | sed 's/ .*$//')
    #"$animals_name" variable contains string after number; for example "white elefant" in case of first line
    animals_name=$(echo "$line" | sed 's/[0-9]* //')
    #"$animals_place" variable contains the string after line which starts with "$animals_number" integer in places.txt file;
    #for example "safari" in case of first line
    animals_place=$(echo "$places" | grep -Ew "^$animals_number" | sed 's/.* //')
    #printf is used to map two strings which share the same integer in the beginning of the line
    printf '%s\t%s\n' "$animals_place" "$animals_name"

#process substitution is used to redirect content of "$animals" variable into sdtin of while loop
done < <(echo "$animals")

但是,我不确定这是解决此问题的最优雅/最有效的方法。任何额外的方法/技术?

4

2 回答 2

3
while read id place;  do places[$id]=$place;                           done < places.txt
while read id animal; do printf '%s\t%s\n' "${places[$id]}" "$animal"; done < animals.txt
于 2012-11-22T18:46:06.320 回答
0
join <(sort animals.txt) <(sort places.txt) | sort -n

不幸的是,join没有“数字排序”选项,afaik;否则,您可以只join对两个文件进行排序,而不是对所有内容进行两次排序。(如果您将前导零放入文件中,它也可以在没有sorts 的情况下工作。)

最近的 ubuntus,可能还有其他 Linux 发行版,设置LANG为您假定的语言环境。这对于 是致命的sort,它是区域感知的,不像join; 上述工作,join并且sort必须同意分拣顺序。如果您收到如下错误:

join: /dev/fd/63:5: is not sorted: 98 white elefant

然后试试这个:

( export LC_ALL=C;  join <(sort animals.txt) <(sort places.txt) | sort -n )
于 2012-11-22T23:34:36.310 回答