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


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

text="this is line onen
this is line twon
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, но как появляется дополнительное пространство?

7 242

7 ответов:

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

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

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

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

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

Если вы отступите строку с вкладками (т. е. '\t'), отступ будет удален. Если вы отступ с пробелами, отступ будет оставлен внутри.

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

echo добавляет пробелы между переданными аргументами. $text подвержен переменному расширению и разбиению слов, поэтому ваш 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

в скрипте 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

cat имя файла дает:

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

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

  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 так, что есть некоторый отступ:

    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"
    

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

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

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

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

String1
String2
String3
...
StringN
_______________________________________________________________________________

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