Как прочитать вперед 1 элемент в цикле и сохранить элемент в переменной в BASH

#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 — это плохо. и, наконец, )) — это просто закрытие арифметического оператора. Смотрите просто 🙂