цикл bash через список рядків


15

Чи можливо форматувати цей зразок:

for i in string1 string2 stringN
do
 echo $i
done

до чогось подібного до цього:

for i in 
string1
string2
stringN
do
 echo $i
done

EDIT: Вибачте за плутанину, не зрозумів, що існують різні способи виконання скрипту - sh <scriptname>vs, bash <scriptname>а також ця річ, яку я зараз не можу назвати - #!/bin/shі #!/bin/bash:)


Яку проблему ви намагаєтеся вирішити?
jesse_b

Ви спробували те, що просите, щоб дізнатися, чи буде це працювати?
DopeGhoti

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

@DopeGhoti так, я зробив

@waayee: У такому випадку масив - найкраща ставка. Дивіться відповідь Глена Джекмана.
jesse_b

Відповіді:


35

Використання масивів у 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, або покладіть належну лінію хешбанг / шебанг і запустіть її як виконуваний файл. Обов'язкове читання: Чи визначає shebang оболонку, яка запускає сценарій?
ilkkachu

1
@rrrrr, ваші запитання, ймовірно , відповів тут: stackoverflow.com/q/12314451/7552
Glenn Джекман

4

Ви можете уникнути розриву лінії за допомогою нахилу:

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

3

Ви можете уникати нових рядків до / після кожного елемента, який ви переходите на цикл:

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
list='a b c d'
for element in $list;do 
    echo "$element"
done

Ви пропускаєте крапки з комою!
41754

Зауважте, що це діятиме до тих пір, поки кожен рядок є окремим словом. Як тільки у вас з’являться пробіли у рядках, пробіли будуть розбивати рядок на кілька слів. Крім того, якщо $listрядок містить символи глобування файлів ( list='* * * *'), оболонка потенційно може замінити їх відповідними іменами.
Кусалаланда

0

Ви можете використовувати loopкоманду, доступну тут , наприклад:

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

або, якщо у вас є список у вигляді файлу:

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

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}
αғsnιη
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.