Почему моя переменная локальна в один, 'в то время как считано' цикл, но не в другом на вид подобном цикле?

Почему бы не использовать stat вместо ls?

stat -c "%y %s %n" *
24
14.12.2017, 04:44
3 ответа

Правильное объяснение было уже дано jsbillings и geekosaur, но позволило мне подробно остановиться на этом немного.

В большинстве оболочек, включая удар, каждая сторона конвейера работает в подоболочке, таким образом, любое изменение во внутреннем состоянии оболочки (таком как установка переменных) остается ограниченным тем сегментом конвейера. Единственная информация, которую можно получить от подоболочки, - то, что она производит (к стандартному выводу и другим дескрипторам файлов) и его код выхода (который является числом между 0 и 255). Например, следующий отрывок печатает 0:

a=0; a=1 | a=2; echo $a

В ksh (варианты, полученные на основании кода AT&T, не pdksh/mksh варианты) и zsh, последний объект в конвейере выполняется в родительской оболочке. (POSIX позволяет оба поведения.), Таким образом, отрывок выше печатает 2.

Полезная идиома должна включать продолжение цикла с условием продолжения (или независимо от того, что Вы имеете на правой стороне конвейера, но некоторое время цикл на самом деле распространен здесь) в конвейере:

cat junk | {
  while read var ; do x=55 ; done
  echo x=$x 
}
25
27.01.2020, 19:41
  • 1
    Спасибо Gilles.. Это a=0; a=1 | a=2 дает очень четкое изображение.. и не только локализации внутреннего состояния, но также и что конвейер ничего не должен на самом деле отправлять через канал (кроме кода выхода (?).. Сам по себе это - интересное понимание канала... Мне действительно удавалось получить мой сценарий, работающий с < <(locate -ber ^\.tag$), благодаря исходному немного неясному ответу и geekosaur и comemnts glenn jackman.. Я первоначально находился в трудном положении о принятии ответа, но результат нетто был довольно ясен, особенно с :) –  Peter.O 24.03.2011, 14:31
  • 2
    такое чувство, что я передал по каналу в функцию, таким образом, я переместил некоторые переменные и тесты к внутренней части, она и это работала отлично, Спасибо! –  Aquarius Power 02.08.2014, 00:04

Вы сталкиваетесь с переменной проблемой объема. Переменные определили в цикле с условием продолжения, который находится на правой стороне канала, имеют их собственный локальный контекст объема, и изменения в переменной не будут замечены за пределами цикла. Цикл с условием продолжения является по существу подоболочкой, которая получает КОПИЮ среды оболочки, и любые изменения в среде потеряны в конце оболочки. Посмотрите этот вопрос о StackOverflow.

ОБНОВЛЕННЫЙ: Я забыл указывать на важное то, что цикл с условием продолжения со своей собственной подоболочкой происходил из-за него являющийся конечной точкой канала, я обновил это в ответе.

8
27.01.2020, 19:41
  • 1
    @jsbillings.. Хорошо, это объясняет два последних отрывка, но это не объясняет первое, где значение набора $x в цикле, продолжен как 55 (вне объема 'в то время как' цикл) –  Peter.O 23.03.2011, 16:39
  • 2
    @fred.bear: это работает while цикл как заключительная часть конвейера, который бросает его в подоболочку. –  geekosaur 23.03.2011, 16:44
  • 3
    Это - то, где замена процесса удара играет роль. Вместо blah|blah|while read ..., Вы можете иметь while read ...; done < <(blah|blah) –  glenn jackman 23.03.2011, 17:01
  • 4
    @geekosaur: благодарит заполнить детали, которые я забыл включать в свой ответ. –  jsbillings 23.03.2011, 17:31
  • 5
    1 Извините, но этот ответ является просто неправильным. Это объясняет, как этот материал работает на многих языках программирования, но не в оболочке. @Gilles, ниже, разобрался в нем. –  jpc 24.03.2011, 05:13
#!/bin/bash
set -x

# prepare test data.
mkdir -p ~/test_var_global
cd ~/test_var_global
echo "a"> core.1
echo "b"> core.2
echo "c"> core.3


var=0

coreFiles=$(find . -type f -name "core*")
while read -r file;
do
  # perform computations on $i
  ((var++))
done <<EOF
$coreFiles
EOF

echo $var

Result:
...
+ echo 3
3

это может сработать.

0
27.01.2020, 19:41

Теги

Похожие вопросы