【问题标题】:ZSH for loop array variable issueZSH for 循环数组变量问题
【发布时间】:2012-06-08 21:29:24
【问题描述】:

我在 工作,但我相信 的说明也会有所帮助。

我需要一个 for 循环来遍历数组 lw 中存储的值,然后根据存储在数组中的名称值启动一个 shell 脚本。

到目前为止,这是我想出的:

$lw=('plugin1' 'plugin2' 'plugin3')

for i in $lw;
  do . ~/Library/Rogall/plugins/$lw[$i]/lw.prg end;
done

运行它给我一个错误,说它找不到~/Library/Rogall/plugins//lw.prg。看起来好像它完全忽略了我的变量。

有什么我搞砸的想法吗?

【问题讨论】:

  • 试试echo $i看看它包含什么。

标签: zsh bash arrays shell unix for-loop zsh


【解决方案1】:

对于其他最终在这里与 shell 脚本、数组和文件名中的空格搏斗的人......就像我下面的文件列表;

$ ls *.meta
20160324 1850 - ABC - Clarke And Dawe.ts.meta
20160706 1515 - 9Gem - Agatha Christie's Poirot.ts.meta
20181213 0155 - 10 BOLD - Star Trek_ The Next Generation.ts.meta
20210424 1927 - ABCTV HD - The Durrells.ts.meta
20210501 1927 - ABCTV HD - The Durrells.ts.meta
20210818 1930 - SBS ONE HD - Tony Robinson's World By Rail.ts.meta

经过大量搜索和尝试不同的方法后,发现问题最少,并且在 MacOS 10.15 上有效

eval "list=( $(find . -name "*.ts" -exec echo \"{}\" \;) )"
for name in "${list[@]}"
do
res=`mediainfo --Output=''Video\;\%Width\%:%Height\%'' "$name"`
echo ${name} :: $res
sed -i .bak -e 5s/\;[[:digit:]]*:[[:digit:]]*// -e 5s/$/\;$res/ "$name.meta" 
done

忽略我试图实现的内部结构,关键方面是使用 eval 并在 find 中的 echo 中将双引号包裹在文件名周围。 (我在做什么?我从 Enigma2 PVR 记录中提取分辨率并将其写入相关元数据文件的第 5 行)

感谢所有发布关于 shell 脚本生成的各种问题的知识的人。

【讨论】:

    【解决方案2】:

    我遇到了这样一个循环的问题

    for i in (1 2 3 4); do echo $i; done
    

    反复没有按我的意愿工作。我会得到像zsh: unknown file attribute: 1 这样的错误,或者像

    这样的输出
    1 2 3 4
    

    无论我如何重新扭曲它,而不是我想要的

    1
    2
    3
    4
    

    为了获得我想要的行为,我必须从循环定义中删除 in 关键字

    for i (1 2 3 4); do echo $i; done
    1
    2
    3
    4
    

    【讨论】:

      【解决方案3】:

      实际上比这简单得多:

      lw=('plugin1' 'plugin2' 'plugin3')
      
      for i in $lw; do
        . ~/Library/Rogall/plugins/$i/lw.prg end
      done
      

      总结:

      • 分配给foo,而不是$foo(shell 会尝试扩展$foo 并分配给它扩展的任何对象;通常没有用)
      • 直接使用循环变量;它包含数组 value 而不是 index

      【讨论】:

      • 这很有意义!谢谢!
      • 或者只是for i ($lw) . ~/Library/Rogall/plugins/$i/lw.prg end
      • 并不是说在一般情况下,for i in $array 会跳过空元素。您需要 for i in "$array[@]"for i in "${(@)array}" 来保留空的(或与 ksh/bash 兼容的语法:for i in "${array[@]}")。
      • @theonlygusti 你的意思是$lw?只需将('plugin1' 'plugin2' 'plugin3') 直接放在$lw 的位置即可。
      【解决方案4】:

      为什么要使用数组呢?这可以很容易地在便携式 sh 中完成:

      lw='plugin1 plugin2 plugin3'
      
      for i in $lw;
        do . ~/Library/Rogall/plugins/$i/lw.prg end
      done
      

      请注意,要使其在 zsh 中工作,您需要使 zsh 正确地使用:set -o shwordsplit

      【讨论】:

      • 并不是所有东西都尽可能地便携,尤其是在 Mac 上运行时(根据目录名称判断)。对于每个单词中可能有空格的一般情况,您的解决方案也失败了。
      • @Moritz 这不是一般情况,而是文件名中没有空格的特殊情况。可移植性可能并不总是必要的,但它始终是一个理想的目标。这个解决方案在 Mac 上运行良好。
      • @Moritz 文件名中的空格令人讨厌!此外,如果文件名中有任何空格,Jan 的解决方案也会失败。
      • 你怎么知道插件目录不包含空格?原始帖子中显示的名称非常通用,可以安全地假设它们不是实际名称。 Jan 的解决方案将在具有某些设置的 zsh 上运行。即使没有,也可以通过两个微不足道的更改来实现。您的解决方案不能轻松地与空格一起使用。但是,唉,诸如“文件名中的空格是可憎的”之类的东西令人难以置信地引起了争论,以至于它甚至都不好笑。但让我们停下来,同意不同意。
      • 如果它依赖于 ZSH 默认值在上下文可能是 .zshrc 文件时被更改,则它是不可移植的。数组是更好的解决方案。
      猜你喜欢
      • 2011-03-02
      • 1970-01-01
      • 2021-12-07
      • 2023-03-04
      • 1970-01-01
      • 2015-09-05
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多