it-roy-ru.com

Многострочная строка с дополнительным пробелом (сохраненный отступ)

Я хочу написать несколько предопределенных текстов в файл со следующим:

text="this is line one\n
this is line two\n
this is line three"

echo -e $text > filename

Я ожидаю что-то вроде этого:

this is line one
this is line two
this is line three

Но получил это:

this is line one
 this is line two
 this is line three

Я уверен, что после каждого \n нет места, но как получить дополнительное пространство?

270
cizixs

Эредок звучит для этого удобнее. Он используется для отправки нескольких команд в программу интерпретатора команд, например ex или cat

cat << EndOfMessage
This is line 1.
This is line 2.
Line 3.
EndOfMessage

Строка после «<<» указывает, где остановиться.

Чтобы отправить эти строки в файл, используйте:

cat > $FILE <<- EOM
Line 1.
Line 2.
EOM

Вы также можете сохранить эти строки в переменной:

read -r -d '' VAR << EOM
This is line 1.
This is line 2.
Line 3.
EOM

Это сохраняет строки в переменной с именем VAR.

При печати запомните кавычки вокруг переменной, иначе вы не увидите символы новой строки.

echo "$VAR"

Более того, вы можете использовать отступы, чтобы они выделялись в вашем коде. На этот раз просто добавьте «-» после «<<», чтобы закладки не появлялись.

read -r -d '' VAR <<- EOM
    This is line 1.
    This is line 2.
    Line 3.
EOM

Но тогда вы должны использовать табуляции, а не пробелы, для отступа в вашем коде.

463
new-kid

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

USAGE=$(cat <<-END
    This is line one.
    This is line two.
    This is line three.
END
)

Если вы сделаете отступ для вашей строки с помощью табуляции (то есть '\ t'), отступ будет удален. Если вы сделаете отступ с пробелами, отступ останется в.

ПРИМЕЧАНИЕ: это / важно, что последняя закрывающая скобка находится в другой строке. Текст END должен появиться в отдельной строке.

104
Andrew Miner

echo добавляет пробелы между переданными ему аргументами. $text подвержен расширению переменных и разбиению Word, поэтому ваша команда echo эквивалентна:

echo -e "this" "is" "line" "one\n" "this" "is" "line" "two\n"  ...

Вы можете видеть, что пробел будет добавлен перед "этим". Вы можете удалить символы новой строки и указать $text, чтобы сохранить новые строки:

text="this is line one
this is line two
this is line three"

echo "$text" > filename

Или вы можете использовать printf, который является более надежным и переносимым, чем echo:

printf "%s\n" "this is line one" "this is line two" "this is line three" > filename

В bash, который поддерживает расширение скобок, вы можете даже сделать:

printf "%s\n" "this is line "{one,two,three} > filename
63
Josh Jolly

в bash-скрипте работает следующее:

#!/bin/sh

text="this is line one\nthis is line two\nthis is line three"
echo $text > filename

альтернативно:

text="this is line one
this is line two
this is line three"
echo "$text" > filename

имя файла кошки дает:

this is line one
this is line two
this is line three
32
Chris Maes

Я нашел больше решений, так как хотел, чтобы каждая строка имела правильный отступ:

  1. Вы можете использовать echo:

    echo    "this is line one"   \
        "\n""this is line two"   \
        "\n""this is line three" \
        > filename
    

    Это не работает, если вы поместите "\n" непосредственно перед \ в конце строки.

  2. Кроме того, вы можете использовать printf для лучшей переносимости (у меня было много проблем с echo):

    printf '%s\n' \
        "this is line one"   \
        "this is line two"   \
        "this is line three" \
        > filename
    
  3. Еще одно решение может быть:

    text=''
    text="${text}this is line one\n"
    text="${text}this is line two\n"
    text="${text}this is line three\n"
    printf "%b" "$text" > filename
    

    или же 

    text=''
    text+="this is line one\n"
    text+="this is line two\n"
    text+="this is line three\n"
    printf "%b" "$text" > filename
    
  4. Другое решение достигается путем смешивания printf и sed

    if something
    then
        printf '%s' '
        this is line one
        this is line two
        this is line three
        ' | sed '1d;$d;s/^    //g'
    fi
    

    Реорганизовать код, отформатированный таким образом, нелегко, поскольку вы жестко закодировали уровень отступа в коде.

  5. Можно использовать вспомогательную функцию и некоторые приемы подстановки переменных:

    unset text
    _() { text="${text}${text+
    }${*}"; }
    # That's an empty line which demonstrates the reasoning behind 
    # the usage of "+" instead of ":+" in the variable substitution 
    # above.
    _ ""
    _ "this is line one"
    _ "this is line two"
    _ "this is line three"
    unset -f _
    printf '%s' "$text"
    
24
Mateusz Piotrowski

это будет работать, если вы поставите его так, как показано ниже:

AA='first line
\nsecond line 
\nthird line'
echo $AA
output:
first line
second line
third line
1
luk

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

read -r -d '' my_variable << \
_______________________________________________________________________________

String1
String2
String3
...
StringN
_______________________________________________________________________________

Количество подчеркиваний одинаково (здесь 80) в обоих случаях.

0
Frank-Rene Schäfer