Bash цикл по списку строк


13

Можно ли отформатировать этот образец:

for i in string1 string2 stringN
do
 echo $i
done

к чему-то похожему на это:

for i in 
string1
string2
stringN
do
 echo $i
done

РЕДАКТИРОВАТЬ: Извините за путаницу, не понимал, что были разные методы выполнения сценария - sh <scriptname>против bash <scriptname>и также эта вещь, которую я не могу назвать прямо сейчас - #!/bin/shи #!/bin/bash:)


Какую проблему вы пытаетесь решить?
jesse_b

Вы пробовали то, что просите, чтобы увидеть, сработает ли это?
DopeGhoti

@Jesse_b удобочитаемость и управляемость набора строк

@ DopeGhoti да, я сделал

@waayee: В этом случае массив - ваш лучший выбор. Смотри ответ Гленна Джекмана.
jesse_b

Ответы:


32

Использование массивов в bash может улучшить читаемость: этот синтаксис массива допускает произвольные пробелы между словами.

strings=(
    string1
    string2
    "string with spaces"
    stringN
)
for i in "${strings[@]}"; do
    echo "$i"
done

1
Это выглядит наиболее элегантно, но, к сожалению, выдает ошибку: Синтаксическая ошибка: "(" неожиданно

1
@waayee, тогда ты не запускаешь его в Bash. Помните, что shэто не обязательно Bash, и особенно не в Debian и Ubuntu.
ilkkachu

1
@ilkkachu Думаю, я понял это сейчас - должен запускать "bash <scriptname>", а не "sh <scriptname>" :)

@waayee, или поместите правильную строку hashbang / shebang и запустите ее как исполняемый файл. Обязательное чтение: определяет ли шебанг оболочку, которая запускает скрипт?
ilkkachu

1
@rrrrr, на ваши вопросы, вероятно, ответят здесь: stackoverflow.com/q/12314451/7552
Гленн Джекман

4

Вы можете избежать разрыва строки с помощью обратной косой черты:

$ for i in \
> hello \
> world
> do
> echo $i
> done
hello
world
$

2

Вы можете экранировать символы новой строки до / после каждого элемента, который вы просматриваете:

for i in \
    string1 \
    string2 \
    stringN
do
   printf '%s\n' "$i"
done

Или для этого простого примера:

printf '%s\n' string1 string2 stringN

который имеет тот же результат.

Связанные с:

Вариация с использованием bashмассива:

strings=(
    string1
    string2
    stringN
)

printf '%s\n' "${strings[@]}"


0

Вы можете использовать loopкоманду, доступную здесь , вот так:

$ loop "echo $ITEM" --for string1,string2,string3

или, если у вас есть список в виде файла:

$ cat file_list.txt | loop "echo $ITEM"

0
list='a b c d'
for element in $list;do 
    echo "$element"
done

Вам не хватает точек с запятой!
41754

Обратите внимание, что это будет работать до тех пор, пока каждая строка является отдельным словом. Как только у вас есть пробелы в строках, пробелы разбивают строку на несколько слов. Кроме того, если $listстрока содержит символы, обозначающие имя файла ( list='* * * *'), оболочка потенциально заменит их соответствующими именами файлов.
Кусалананда

0

То же самое, меньше текста:

array=(
        string{1..7}
)

for i in "${array[@]}"; do
    echo "$i"
done

string1и т. д. не являются литеральными значениями, которые должны отображаться, а являются заполнителями, поэтому этот подход не работает.
Стивен Китт

если да, то зачем array ( … )? просто делай for i in string{1..7}; do echo "$i"; done; дажеprintf '%s\n' string{1..7}
αғsнιη
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.