Bash 声明性地定义要循环的列表

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/10687313/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-18 02:20:47  来源:igfitidea点击:

Bash declaratively defining a list to loop on

bashloops

提问by Adam Gent

In bash I frequently make scripts where I loop over a list of strings that I define.

在 bash 中,我经常在脚本中循环我定义的字符串列表。

e.g.

例如

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:

但是,我想定义列表(在循环之前以保持清洁),以便它包含空格并且没有单独的文件:

e.g. (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 filebefore the for loop logic

抱歉我忘了提到我想在 for 循环逻辑之前定义文件顶部的列表

回答by choroba

You can use the "HERE Document" like this:

您可以像这样使用“HERE 文档”:

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

回答by chepner

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.

如果您有需要,这具有允许每个列表项包含空格的额外好处。

回答by Paused until further notice.

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

回答by mVChr

There are better answers here, but you can also delimit the read on \nand temporarily change the variable to split on newlines instead of whitespace in the forloop using the IFSenvironment variable.

这里有更好的答案,但您也可以使用环境变量分隔读取\n并临时更改变量以在换行符上拆分而不是在for循环中使用空格IFS

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

回答by Dr. Jan-Philip Gehrcke

When it's fine for you to use a whileloop instead of a forloop, you can make use of the while readconstruct and a "here document":

当您可以使用while循环而不是for循环时,您可以使用while read构造和“此处文档”:

#!/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?

参考:` cat << EOF` 在 bash 中如何工作?