Bash:逐行读取文件并将每个段作为其他程序的参数处理

38

我有一些琐碎的工作要做,所以Bash脚本似乎是一个不错的选择。我对Bash还很陌生,这让我感到有点沮丧。

文件mapfiles.txt由以下行组成。每行由四个由空格分隔的部分组成。每个部分都代表外部程序名称“prog”的输入参数。例如,“cm19_1.png”是文件名,“0001”是索引,“121422481”是经度,“31035995”是纬度

文件: mapfiles.txt

cm19_1.png 0001 121422481 31035995
cm19_2.png 0002 121423224 31035995
cm19_3.png 0003 121423967 31035995
…

我想对每一行执行类似的命令。如下所示,prog的输入参数顺序略有不同。因此编写一个bash脚本来处理重复工作是有意义的。

[Usage] prog <index> <longitude> <latitude> <filename>
example: prog 0001 121422481 31035995 cm19_1.png

一般来说,bash脚本会按照以下方式运行:

  1. 从mapfiles.txt中读取一行
  2. 分割segments
  3. 使用正确的参数顺序调用程序

这里是run.sh。

#!/bin/sh

input=mapfiles.txt
cmd=prog

while read line
do
        file=$(echo $line | cut -d' ' -f1)
        key=$(echo $line | cut -d' ' -f2)
        log=$(echo $line | cut -d' ' -f3)
        lat=$(echo $line | cut -d' ' -f4)
        echo $cmd $key $log $lat $file
done < "$input"

我期望的是什么

prog 0001 121422481 31035995 cm19_1.png
prog 0002 121423224 31035995 cm19_2.png
prog 0003 121423967 31035995 cm19_3.png
… 

我实际得到的结果是

 cm19_1.png21422481 31035995
 cm19_2.png21423224 31035995
 cm19_3.png21423967 31035995

困扰我的问题

  1. 'prog'在哪里?
  2. 空格在哪里?
  3. 参数顺序有什么问题?

嗯...我在我的Mac上使用vim编写了这个脚本,然后将它复制到Scientific Linux和gentoo box上,这三个系统都输出了相同的荒谬结果。


1
无法在此处重现。请查找拼写错误。另外,使用read file key log lat代替所有的切割。更新请查看答案。 - n. m.
当与ssh结合在循环中时,请查看此问题:https://dev59.com/E2ox5IYBdhLWcg3wKBN9 - Christian
3个回答

52

你可以大大简化这个:

while read file key log lat
do
  echo "$cmd" "$key" "$log" "$lat" "$file"
done < "$input"

11
您可以将其进一步简化。 您不需要为每个参数使用单独的变量:while read line; do echo $cmd $line; done < "$input" - Idelic

10

使用GNU Parallel,您可以在一行代码中完成此操作,并且完全免费地并行处理:

cat mapfile.txt | parallel --colsep '\s' prog {2} {3} {4} {1}

观看介绍视频以了解更多信息:http://www.youtube.com/watch?v=OpaiGYxkSuQ


2
prog可能已经消失了,因为$cmd未被导出。你的/bin/sh版本可能会在单独的shell中执行while语句。这不应该是这种情况,在我安装的bash中也不是这种情况,但也许你的行为在这个部门有一些有趣的方式。 更新:我看到你有几个盒子给出了相同的结果。这使得子shell理论不太可能。也许你的脚本和/或源文件中有一些有趣的字符。
我已经将你的脚本和源文件复制并粘贴到我的Gentoo盒子上,它给出了预期的结果。也许你应该做同样的事情,并将文件与原始文件进行比较。

2
非常感谢。您的评论帮助我找出了真正出错的原因。问题不在Bash脚本上 - 我在三个不同的盒子上测试过了 - 而是mapfiles.txt出了问题。该文件在Windows中生成,每行结尾都有^M。删除^M后,一切都正常了。 - Jianwen W.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接