7

我正在尝试将文件作为行数组读取,然后使用 zsh 对其进行迭代。我得到的代码大部分时间都有效,除非输入文件包含某些字符(例如括号)。这是它的一个片段:

#!/bin/zsh
LIST=$(cat /path/to/some/file.txt)
SIZE=${${(f)LIST}[(I)${${(f)LIST}[-1]}]}
POS=${${(f)LIST}[(I)${${(f)LIST}[-1]}]}
while [[ $POS -le $SIZE ]] ; do
    ITEM=${${(f)LIST}[$POS]}
    # Do stuff
    ((POS=POS+1))
done

我需要进行哪些更改才能使其正常工作?

4

3 回答 3

17
#!/bin/zsh
zmodload zsh/mapfile
FNAME=/path/to/some/file.txt
FLINES=( "${(f)mapfile[$FNAME]}" )
LIST="${mapfile[$FNAME]}" # Not required unless stuff uses it
integer POS=1             # Not required unless stuff uses it
integer SIZE=$#FLINES     # Number of lines, not required unless stuff uses it
for ITEM in $FLINES
    # Do stuff
    (( POS++ ))
done

你的代码中有一些奇怪的东西:

  1. 为什么LIST每次都拆分而不是使其成为数组变量?这只是浪费CPU时间。
  2. 你为什么不使用for ITEM in ${(f)LIST}
  3. 有可能直接向 zsh 询问数组长度:$#ARRAY。无需确定最后一个元素最后一次出现的索引。
  4. POSSIZE获得与您的代码中相同的值。因此它只会迭代一次。
  5. 括号是问题可能是因为 3.:(I)与模式匹配。请阅读文档。
于 2012-09-29T11:23:34.030 回答
14

我知道问题得到解答已经有很长时间了,但我认为值得发布一个更简单的答案(不需要 zsh/mapfile 外部模块):

#!/bin/zsh
for line in "${(@f)"$(</path/to/some/file.txt)"}"
{
  // do something with each $line
}
于 2016-12-18T20:56:38.730 回答
0

假设,出于示例的目的,它file.txt包含以下文本:

one

two

three

解决方案取决于您是否要省略空行file.txt


  • lines从文件创建一个数组file.txt省略空行

    typeset -a lines=("${(f)"$(<file.txt)"}")
    
    print ${#lines}
    

    预期输出:

    3
    

  • lines从文件创建一个数组file.txt不省略空行

    typeset -a lines=("${(@f)"$(<file.txt)"}")
    
    print ${#lines}
    

    预期输出:

    5
    

最后,结果数组的差异是在大括号扩展期间是否提供了参数扩展标志的结果。 (@)

于 2021-10-28T11:52:54.507 回答