Значение переменной теряется в подоболочке - PullRequest
3 голосов
/ 21 июня 2010

Этот скрипт bash объединяет имена файлов jar в classpath (переменная CP), в цикле while значение правильное, но оно теряется в подоболочке, как описано в этом связанном вопросе Область действия переменной Bash

#!/bin/bash
CP="AAA"
func() {
        ls -1 | while read JAR
        do
                if [ ! -z "$CP" ]; then
                        CP=${CP}':'
                fi
                CP=${CP}${JAR}
        done
        echo $CP # <-- prints AAA
}

func

У меня вопрос, поскольку я не могу понять, какой элемент будет последним, как можно сохранить значение.

Должен ли я на самом деле сохранить текущее значение (многократно в цикле) в файл?

EDIT:

Коллега придумал эту последовательность команд, которая хорошо работает

ls | xargs echo|tr ' ' :

Ответы [ 5 ]

6 голосов
/ 21 июня 2010

Проблема здесь в том, что использование while в конвейере создает подоболочку, и подоболочка не может влиять на своего родителя. Вы можете обойти это несколькими способами. Для того, что вы делаете сейчас, этого будет достаточно:

for JAR in *; do
    # Your stuff
done

Еще одна вещь, на которую стоит обратить внимание: вы не должны полагаться на разбор ls

Этот также показывает вам способы избежать подоболочки.

1 голос
/ 22 июня 2010

Возможно, вы найдете использование find более универсальным.

Например:

export CP=$( find /home/depesz/q/ -maxdepth 1 -type f -name '*.jar' -printf ':%p' | cut -b 2- )

Конечно, набор параметров поиска зависит от того, что вам нужно / нужно.

Это ближе к тому, что вы имели ранее:

export CP=$( find . -maxdepth 1 -type f -name '*.jar' -printf ':%f' | cut -b 2- )
0 голосов
/ 13 ноября 2017

Похоже, что ни один из этих ответов не приводит к правильному возвращению значения, повторение ответа хорошо с очень простой процедурой, но, скажем, вы хотите, чтобы вывод скрипта в действии, это бесполезно.У меня нет лучшего ответа, но у меня не так много времени, чтобы выяснить это, поэтому я просто собираюсь предложить вывести именно то, что вы хотите, во временный файл и прочитать его (удивительно, что это не былоупомянуто на сегодняшний день):

#!/bin/bash
CP="AAA"
func() {
  ls -1 | (
    while read JAR
    do
      if [ ! -z "$CP" ]; then
        CP=${CP}':'
      fi
      CP=${CP}${JAR}
    done
    echo "$CP" > /tmp/cp-value-file
  )
}

func
CP=$(cat /tmp/cp-value-file)
echo $CP

Недостаток: в некоторых случаях потребуется записывать на диск каждую итерацию цикла.

0 голосов
/ 17 мая 2012

Вот еще одно решение, которое полностью исключает порождение подоболочки.Ключ заключается в том, чтобы захватить входные данные цикла в переменную (в моем примере это называется «JARS»), а затем перенаправить эту переменную в цикл, используя << EOF: </p>

JARS=$(ls -1)

while read JAR
do
        if [ ! -z "$CP" ]; then
                CP=${CP}':'
        fi
        CP=${CP}${JAR}
done <<EOF
$JARS
EOF

echo $CP
0 голосов
/ 22 июня 2010

Неявные подоболочки сбивают с толку;всегда делайте их явными, используя скобки.Чтобы решить вашу проблему, просто переместите эхо внутри подоболочки.

#!/bin/bash
CP="AAA"
func() {
  ls -1 | (
    while read JAR
    do
      if [ ! -z "$CP" ]; then
        CP=${CP}':'
      fi
      CP=${CP}${JAR}
    done
    echo $CP
  )
}
func
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...