Почему `read -r` по-прежнему получает только первое слово в каждой строке?

Этот вопрос относится к моему старшему здесь .

После того, как я наконец-то узнал, как обойти вывод git в функцию, у меня теперь другая проблема. Использование

git clone --progress XYZ &> git_clone.file

записывает как ожидалось

Cloning to 'someRepository' ...
remote: Counting objects: 2618, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 2618 (delta 2), reused 12 (delta 1), pack-reused 2603
Received objects: 100% (2618/2618), 258.95 MiB | 4.39 MiB/s, Done.
Resolving Differences auf: 100% (1058/1058), Done.
Check Connectivity ... Done.

в git_clone.file.

Теперь я не хочу перенаправлять вывод в файл, но в функцию, поэтому я использую

function PrintInfo(){
    tput el
    echo $1
    <Print ProgressBar> 
    #For further details about this see 
    # https://askubuntu.com/questions/988403/bash-pass-command-output-to-function-in-realtime
}

git clone --progress XYZ |& {
    while read -r line
    do
        PrintInfo $line
    done
}

Теперь я ожидаю получить

Cloning to 'someRepository' ...
remote: Counting objects: 2618, done.
remote: Compressing objects: 100% (14/14), done.
remote: Total 2618 (delta 2), reused 12 (delta 1), pack-reused 2603
Received objects: 100% (2618/2618), 258.95 MiB | 4.39 MiB/s, Done.
Resolving Differences auf: 100% (1058/1058), Done.
Check Connectivity ... Done.

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

Cloning
remote:
remote:
Received
...

и так далее. Я уже пробовал все формы IFS, такие как

... while IFS= read -r ...

... while IFS='' read -r ...

... while IFS="\n" read -r ...

, но ни одна из них не решает эту проблему.

Как прочитать полную строку вывода?

3
задан 24 December 2017 в 11:51

1 ответ

Проблема заключается в разбиении слов . Чтобы решить ее, замените:

PrintInfo $line

на:

PrintInfo "$line"

Объяснение

Рассмотрим:

PrintInfo $line

Перед выполнением, PrintInfo оболочка расширится $line и выполнит как разбиение слов , так и расширение пути .

Давайте рассмотрим простой пример, начав с определения функции:

$ PrintInfo() { echo "1=$1 2=$2 3=$3"; }

Теперь давайте выполним функцию:

$ line="one two three"
$ PrintInfo $line
1=one 2=two 3=three

В приведенном выше примере разбиение слов заставил PrintInfo увидеть три аргумента.

Если вы хотите, чтобы PrintInfo видел только один аргумент, используйте:

$ PrintInfo "$line"
1=one two three 2= 3=

Расширение имени пути также является потенциальной проблемой. Рассмотрим каталог с этими файлами:

$ ls
file1  file2  file3

Теперь давайте снова запустим нашу версию PrintInfo:

$ line='file?'
$ PrintInfo $line
1=file1 2=file2 3=file3

Поскольку ? является допустимым глобальным символом, оболочка выглядит заменить file? именами файлов. Чтобы избежать этого сюрприза, используйте двойные кавычки:

$ PrintInfo "$line"
1=file? 2= 3=

Резюме

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

5
ответ дан 24 December 2017 в 11:51

Другие вопросы по тегам:

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