【问题标题】:Bash: Making cat merge braced files {} in a variableBash:在变量中制作 cat 合并大括号文件 {}
【发布时间】:2019-01-22 18:20:42
【问题描述】:

问题:

cat 工作在大括号{} 内读取多个文件;

cat {file1,file2}.txt

但当大括号部分由变量指定时则不然。

VAR="{file1,file2}"
cat $VAR.txt

我怀疑,正如引用的here,这是因为引号是在变量中逐字读取的。所以cat 试图找到不存在的{file1,file2}.txt

有没有办法将多个文件指定为变量中的单个元素?

上下文:

对于我的完整脚本,我想通过一组带括号和不带括号的文件前缀循环 cat。所以简单地设置VAR=( file1 file2) 对我没有帮助。

VAR=( "{file1,file2}" file3 file4 )
for i in ${VAR[@]}; do cat $i.txt > merged$i.txt; done

【问题讨论】:

  • 还要注意echo file{1,2,3} 将始终返回file1 file2 file3,而不管这些文件是否真的存在...
  • @glenn jackman:谢谢。我已编辑我的帖子以删除引号。
  • VAR=( {file1,file2} file3 file4 ) 可以正常工作。为什么要引用这些字符串?
  • 顺便说一句,它应该是for i in "${VAR[@]}"; do cat "$i.txt" > "merged$i.txt"; done——如果您想对所有可能的文件名、IFS 值等进行正确操作,则引号不是可选的。
  • 我引用了字符串以得到{file1,file2} 作为for in ${VAR[@]}; do echo $i; done 的输出。我希望cat 在循环的一次迭代中读取和合并这两个文件。

标签: bash variables cat braces


【解决方案1】:

Brace expansion is the first thing bash does,因此您不能将其存储在变量中(除非您求助于eval

使用数组时只需删除引号:

$ files=( file{1..4} )
$ declare -p files
declare -a files='([0]="file1" [1]="file2" [2]="file3" [3]="file4")'

然后

cat "${files[@]}" > merged

【讨论】:

  • 另外,不要使用全大写变量名。你将不可避免地覆盖一个关键的 shell 变量,比如 PATH。
  • @glenn jackman:感谢您对语法的说明,您让我免于未来的一些潜在问题。有没有办法使用declare 将“file1”和“file2”视为变量中的相同元素?我只想合并某些文件,所以我输出“file1+2”、“file3”和“file4”。
  • 不安全。听起来您想使用eval 并冒着恶意文件名的风险。此外,如果这是一个关键要求,它属于你的问题——我不知道这是你想要的。
  • 看来eval 是要走的路。我会仔细研究的。我还尝试将问题编辑得更直接,感谢您的帮助。
【解决方案2】:

eval 是你要找的吗?

VAR="{file1,file2}"
eval "cat $VAR.txt"

【讨论】:

  • eval is dangerous尤其是在文件名的上下文中。在没有警告的情况下鼓励使用它不是很好的做法。
  • 我累了,它工作。但是,它似乎在循环中不起作用。我会用循环来寻找解决方案,谢谢。
  • @JamesReeve, ...很多东西看起来像当它们只在简单的情况下进行测试时,它们在 bash 中工作,但有微妙的,甚至是危险的错误。如果你幸运的话,那些细微的错误只是意味着你的脚本在对带有​​空格的文件名进行操作时会失败,但滥用eval 通常意味着你的脚本会因为将文件名作为代码执行而失败——所以如果你是个小丑跑touch '$(rm -rf ~)',不安全eval-使用代码可以破坏你的整个主目录。
猜你喜欢
  • 2015-01-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多