9

您如何在 bash 中同步读取/处理 2 个文件?

我有 2 个文本文件,它们的行数/项目数相同。一个文件是

a
b
c

另一个文件是

1
2
3

如何同步循环遍历这些文件,以便a1、b->2、c->3 关联?

我以为我可以将文件作为数组读取,然后用索引处理它们,但似乎我的语法/逻辑不正确。

这样做f1=$(cat file1)使f1 = a b c. 我认为这样做f1=($(cat file1))会将它变成一个数组,但它会生成f1=a,因此没有数组供我处理。

如果有人想知道我搞砸的代码是什么:

hostnames=($(cat $host_file))  
# trying to read in as an array, which apparently is incorrect
roles=($(cat $role_file))

for i in {0..3}
do
   echo ${hostnames[$i]}   
   # wanted to iterate through each element in the file/array
   # but there is only one object instead of N objects
   echo ${roles[$i]}
done
4

7 回答 7

17

您可以使用文件描述符

while read -r var_from_file1 && read -r var_from_file2 <&3; do 
    echo "$var_from_file1 ---> $var_from_file2"
done <file1 3<file2

输出:

a ---> 1
b ---> 2
c ---> 3
于 2013-06-21T19:55:22.710 回答
10

使用paste( invocation ) 合并文件,然后一次处理合并文件的一行:

paste file1 file2 |
while read -r first second
do
  echo $first
  echo $second
done
于 2013-06-21T19:53:51.253 回答
2

GNU 的代码:

  • 前面有file1

    sed -r 's#(.*)#s/(.*)/\1 \\1/;$!n#' file1|sed -rf - file2
    

    或者

  • 前面有file2

    sed -r 's#(.*)#s/(.*)/\\1 \1/;$!n#' file2|sed -rf - file1
    

两者都导致相同的输出:

一个 1
b 2
3
d 4
5
f 6
克 7
于 2013-06-21T20:23:38.713 回答
2

你的方式:

host_file=host1
role_file=role1

hostnames=(  $(cat $host_file) )  
roles=( $(cat $role_file)  )
(( cnt = ${#hostnames[@]}  -1 ))
echo "cnt is $cnt"
for (( i=0;i<=$cnt;i++))
do
  echo "${hostnames[$i]} ->    ${roles[$i]}"
done
于 2013-06-21T20:46:40.803 回答
2

的两个例子:

awk '{print $0, NR}' file1

和 - 好多了:-)

awk 'NR==FNR {a[NR]=$0;next};{print a[FNR], $0}' file1 file2

..输出总是:

a 1
b 2
c 3
于 2013-06-21T20:59:47.740 回答
2

这个问题的一个简洁灵活的解决方案是 core-util pr

# space separated
$ pr -mts' ' file1 file2
a 1
b 2
c 3

# -> separated
$ pr -mts' -> ' file1 file2
a -> 1
b -> 2
c -> 3

有关man pr更多信息,请参阅。

于 2013-06-29T21:44:49.120 回答
0

纯重击:

IFS=$'\n'
hostnames=( $( <hostnames.txt ) )
roles=( $( <roles.txt ) )

for idx in ${!hostnames[@]}; do    # loop over array indices
  echo -e "${hostnames[idx]} ${roles[idx]}"
done

或在 gniourf_gniourf 的评论之后

mapfile -t hostnames < hostnames.txt
mapfile -t roles < roles.txt

for idx in ${!hostnames[@]}; do              # loop over array indices
  echo -e "'${hostnames[idx]}' '${roles[idx]}'"
done
于 2013-06-22T08:15:34.753 回答