#bash #shell #loops
#bash #оболочка #циклы
Вопрос:
Как сделать,
У меня есть список строк, которые содержат по одному элементу в строке. Что я хочу сделать, так это сохранить второй элемент в переменной и отобразить его эхом. У меня написан следующий код
#!/bin/bash
LIST='jeremy
test
bob
test2'
for i in $LIST
do
TEMP=$[i 1]
echo $TEMP
done
Теперь, я думаю, во время выполнения цикла просто переместите индекс 1 и сохраните этот элемент в переменной. Однако, когда я запускаю код, я получаю следующее:
1
1
СПИСОК — это, по сути, массив, так как вы читаете вперед на один элемент и сохраняете этот элемент как переменную, а затем перемещаете индекс на одно место вперед?
Поэтому, когда скрипт запускается, он сохраняет ‘test’ как temp и выдает его эхом. Затем индекс будет перемещен в ‘bob’ и сохранен ‘test2’ как temp.
Я пробовал i
Я пробовал i = i 1
Есть идеи?
Ответ №1:
Я думаю, что здесь есть некоторая путаница между элементами массива («jeremy», «test» и т.д.) И индексами элементов (0, 1 и т.д.). При использовании TEMP=$[i 1]
вы пытаетесь добавить 1 к «jeremy», что не имеет никакого смысла. Вам нужно добавить 1 к индексу «jeremy» и получить элемент с этим индексом (в данном случае «test»). Но для того, чтобы сделать это, вам нужно выполнить цикл по индексам массива ( "${!list[@]}"
— обратите внимание на восклицательный знак), а не по его элементам ( "${list[@]}"
). Вот как это выглядит:
list=(jeremy test bob test2)
for i in "${!list[@]}"; do
thiselement="${list[i]}"
nextelement="${list[i 1]}"
echo "This element=$thiselement, next element=$nextelement"
done
вывод:
This element=jeremy, next element=test
This element=test, next element=bob
This element=bob, next element=test2
This element=test2, next element=
Обратите внимание, что для последнего элемента попытка получить следующий просто возвращает пустую строку. Если вы хотите что-то еще, используйте тест, подобный
if (( i 1 < ${#list[@]} )); then
nextelement="${list[i 1]}"
else
nextelement="End of the list"
fi
Ответ №2:
Используйте правильный синтаксис BASH array
:
list=(jeremy test bob test2)
for i in "${list[@]}"
do
echo "$i"
done
кстати, избегайте использования всех имен переменных caps в BASH, чтобы избежать перехода через некоторую предопределенную переменную env.
Комментарии:
1. Мне нравится этот формат, но как бы я прочитал во втором вводе и сохранил его как переменную? В настоящее время вы выполняете цикл скрипта, но он будет считывать каждый элемент за раз. Мне нужно сохранить каждый 2-й элемент как переменную
2. 2-й элемент просто
"${list[1]}"
3. Большое вам спасибо. Теперь у меня есть единственный вопрос, как бы я переместил индекс или, в данном случае, i 1, чтобы после того, как он прочитал jeremy, следующим элементом, который он прочитал, был бы bob
4. @Джимми, лучший ответ «не делай этого». извлечение массива bash — это операция O (n) (что означает, что она медленнее в зависимости от количества элементов в массиве); мы могли бы рассказать вам, как это сделать, но у этого была бы плохая производительность, поэтому лучше, если вы напишете свои сценарии, которые не нуждаются или не хотят этого делать. (Справедливости ради — можно сделать его O (1), если вы не переиндексируете, но это вызывает другие ошибки, поскольку это означает, что
${array[0]}
больше не является первой записью).
Ответ №3:
LIST=( jeremy test bob test2 )
let count=0
for i in ${LIST[@]}
do
if [[ $count -lt $((${#LIST[@]}-1)) ]]; then
TEMP=${LIST[$((count 1))]}
fi
echo "LIST [$count] = ${LIST[$count]} TEMP = $TEMP"
((count =1))
done
вывод:
LIST [0] = jeremy TEMP = test
LIST [1] = test TEMP = bob
LIST [2] = bob TEMP = test2
LIST [3] = test2 TEMP = test2
Комментарии:
1. Когда я запускаю ваш код, я фактически получаю 0 выходных данных. Я все еще отслеживаю, чтобы понять, почему, но я получаю 0 выходных данных
2. Извините, у меня была ошибка. Ваш код постоянно возвращает тест. Это не переход ко второму элементу и распечатка. Например, когда я запускаю ваш код: sh final_pw.sh тестовый тестовый тестовый тест
3. Вы правы. Изначально я прочитал вам определение
LIST
как массив вместо строки. Извините. Вам нужно создатьLIST
массив, если вы хотите получитьI 1
элемент. Извлечение строки — это беспорядок.4. Вы джентльмен и ученый. Большое вам спасибо. Я немного смущен самим кодом. Более конкретно, $count -lt $((${#LIST[@]}-1))
5. Алфавитный суп довольно прост, когда вы разбираете его на части. Внешний
$((
— это арифметический оператор, внутренний${#LIST[@]}
говорит получить количество элементов в массиве,- 1
говорит не делать этого для последнего элемента. чтениеlast 1
— это плохо. и, наконец,))
— это просто закрытие арифметического оператора. Смотрите просто 🙂