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[@]}"
Кусалананда
источник
1

Если переключение на zshвариант:

for string (
  string1
  'other string'
  etc..
) printf '%s\n' "$string"
Стефан Шазелас
источник
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нιη