简体   繁体   English

Bash以声明方式定义要循环的列表

[英]Bash declaratively defining a list to loop on

In bash I frequently make scripts where I loop over a list of strings that I define. 在bash中,我经常创建脚本,循环遍历我定义的字符串列表。

eg 例如

for a in 1 2 3 4; do echo $a; done

However I would like to define the list (before the loop to keep it clean) so that it contains spaces and with out a separate file: 但是我想定义列表(在循环之前保持它干净),以便它包含空格并且没有单独的文件:

eg (BUT THIS WILL NOT WORK) 例如(但这不起作用)

read -r VAR <<HERE
list item 1
list item 2
list item 3
...
HERE

for a in $VAR; do echo $a; done

The expected output above (I would like): 上面的预期输出(我想):

list item 1
list item 2
list item 3
etc...

But you will get: 但你会得到:

list
item
1

I could use arrays but I would have to index each element in the array ( EDIT read answers below as you can append to arrays.. I did not know you could ). 我可以使用数组,但我必须索引数组中的每个元素( 编辑读取下面的答案,因为你可以附加到数组..我不知道你可以 )。

How do others declaratively define lists in bash with out using separate files? 其他人如何在bash中声明性地定义列表而不使用单独的文件?

Sorry I forgot to mention I want to define the list at the top of the file before the for loop logic 对不起,我忘了提到我想在for循环逻辑之前定义文件顶部的列表

You can use the "HERE Document" like this: 您可以像这样使用“HERE Document”:

while read a ; do echo "Line: $a" ; done <<HERE
123 ab c
def aldkfgjlaskdjf lkajsdlfkjlasdjf
asl;kdfj ;laksjdf;lkj asd;lf sdpf -aa8
HERE

Arrays aren't so hard to use: 数组不是那么难用:

readarray <<HERE
this is my first line
this is my second line
this is my third line
HERE

# Pre bash-4, you would need to build the array more explicity
# Just like readarray defaults to MAPFILE, so read defaults to REPLY
# Tip o' the hat to Dennis Williamson for pointing out that arrays
# are easily appended to.
# while read ; do
#    MAPFILE+=("$REPLY")
# done

for a in "${MAPFILE[@]}"; do
    echo "$a"
done

This has the added benefit of allowing each list item to contain spaces, should you have that need. 如果您有这种需要,这还有一个额外的好处,即允许每个列表项包含空格。

while read -r line
do
    var+=$line$'\n'
done <<EOF
foo bar
baz qux
EOF

while read -r line
do
    echo "[$line]"
done <<<"$var"

Why would you need to index arrays? 为什么需要索引数组? You can append to arrays and iterate over them without using indices. 您可以附加到数组并迭代它们而不使用索引。

array+=(value)
for item in "${array[@]}"
do
    something with "$item"
done

There are better answers here, but you can also delimit the read on \\n and temporarily change the variable to split on newlines instead of whitespace in the for loop using the IFS environment variable. 这里有更好的答案,但您也可以分别对\\n进行读取,并使用IFS环境变量临时更改变量以分隔换行而不是for循环中的空格。

read -d \n -r VAR <<HERE
list item 1
list item 2
list item 3
HERE

IFS_BAK=$IFS
IFS="\n"
for a in $VAR; do echo $a; done
IFS=$IFS_BAK

When it's fine for you to use a while loop instead of a for loop, you can make use of the while read construct and a "here document": 如果你可以使用while循环而不是for循环,你可以使用while read结构和“here document”:

#!/bin/bash

while read LINE; do
    echo "${LINE}"
done << EOF
list item 1
list item 2
list item 3
EOF

ref: How does ` cat << EOF` work in bash? ref: `cat << EOF`如何在bash中运行?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM