Назначение переменной при чтении из файла с помощью cat

У меня есть текстовый файл следующего формата:

name1    path/to/some/directory
name2    path/to/some/other/directory
name3    path/to/some/directory
name4    path/to/some/other/directory 
...

Вот код, который я написал для чтения этого файла построчно:

NUM=1
for line in $(cat /path/to/my/file.txt);  do
if [ $((NUM%2)) -eq 1 ]
then 
    name= $line #this line does not work
    echo $line #while this line works just fine

else 
    sudo tar -cf /desired/path/$name.tar $line
fi
NUM=$((NUM+1))
done

Этот код фактически читает файл слово за словом, и он чередует then и else в инструкции if. Как только он присваивает прочитанное значение имени переменной (then внутри if), он использует эту переменную в команде, которая выполняется в else часть if. (Вот как я ожидаю, что это сработает.)

Возникающая проблема заключается в том, что назначение переменной в then части , если кажется, не работает, он видит слово, которое он только что прочитал как команду, и не присваивает его значение Переменная. Я попытался повторить его, и он работает нормально.

Почему name= $line присвоение переменных не работает?

Спасибо за любые предложения, комментарии или ответы.


person balboa    schedule 12.12.2014    source источник


Ответы (1)


Присваивания в bash не требуют места вокруг =.

Следовательно, вам нужно сказать:

name="$line"
     ^     ^
     quotes!

Это происходит потому, что все, что происходит после объявления, считается командой. См., Например, это, который пытается определить r в 2, а затем выполняется echo 1:

$ r=2 echo 1
1

Вот почему также полезно процитировать декларацию: name="$line".


Что касается синтаксического анализа и определения переменных файла, вы можете использовать этот подход:

declare $('s/\s\+/="/; s/$/"/' a)

Это заменяет пробелы между первым и вторым словом на =", а в конце строки на ". Таким образом, name /path/ преобразуется в name="/path/". При использовании declare эта команда выполняется и готовит переменные к использованию.

$ cat a
name1 aa
name2 rr
name5 hello
$ sed 's/\s\+/="/; s/$/"/' a
name1="aa"
name2="rr"
name5="hello"
$ declare $('s/\s\+/="/; s/$/"/' a)

Итак, теперь у вас есть переменные, готовые к использованию:

$ echo "$name5"
hello

И, наконец, обратите внимание, что это эквивалентно (и лучше), чем for line in $(cat /path/to/my/file.txt):

while IFS= read -r val1 val2 ...
do
    ... things ...
 done < /path/to/my/file.txt
person fedorqui 'SO stop harming'    schedule 12.12.2014
comment
Спасибо за подробный ответ, с четкими и конкретными пояснениями ... Я изменил свой код и узнал новое ... вы помогли :) - person balboa; 12.12.2014