Попытка встраивания новой строки в переменную в bash

У меня

var="a b c"
for i in $var
do
   p=`echo -e $p'\n'$i`
done
echo $p

Я хочу, чтобы последнее эхо печаталось

a
b
c

Обратите внимание, что я хочу, чтобы переменная p содержала символы новой строки. Как это сделать?

Ответы

Ответ 1

Резюме

  • Вставка \n

    p="${var1}\n${var2}"
    echo -e "${p}"
    
  • Вставка новой строки в исходный код

    p="${var1}
    ${var2}"
    echo "${p}"
    
  • Использование $'\n' (только и )

    p="${var1}"$'\n'"${var2}"
    echo "${p}"
    

Подробнее

1. Вставка \n

p="${var1}\n${var2}"
echo -e "${p}"

echo -e интерпретирует два символа "\n" как новую строку.

var="a b c"
first_loop=true
for i in $var
do
   p="$p\n$i"            # Append
   unset first_loop
done
echo -e "$p"             # Use -e

Избегайте дополнительной командной строки

var="a b c"
first_loop=1
for i in $var
do
   (( $first_loop )) &&  # "((...))" is bash specific
   p="$i"            ||  # First -> Set
   p="$p\n$i"            # After -> Append
   unset first_loop
done
echo -e "$p"             # Use -e

Используя функцию

embed_newline()
{
   local p="$1"
   shift
   for i in "[email protected]"
   do
      p="$p\n$i"         # Append
   done
   echo -e "$p"          # Use -e
}

var="a b c"
p=$( embed_newline $var )  # Do not use double quotes "$var"
echo "$p"

2. Вставка новой строки в исходный код

var="a b c"
for i in $var
do
   p="$p
$i"       # New line directly in the source code
done
echo "$p" # Double quotes required
          # But -e not required

Избегайте дополнительной командной строки

var="a b c"
first_loop=1
for i in $var
do
   (( $first_loop )) &&  # "((...))" is bash specific
   p="$i"            ||  # First -> Set
   p="$p
$i"                      # After -> Append
   unset first_loop
done
echo "$p"                # No need -e

Используя функцию

embed_newline()
{
   local p="$1"
   shift
   for i in "[email protected]"
   do
      p="$p
$i"                      # Append
   done
   echo "$p"             # No need -e
}

var="a b c"
p=$( embed_newline $var )  # Do not use double quotes "$var"
echo "$p"

3. Использование $'\n' (менее портативный)

и интерпретирует $'\n' как новую строку.

var="a b c"
for i in $var
do
   p="$p"$'\n'"$i"
done
echo "$p" # Double quotes required
          # But -e not required

Избегайте дополнительной командной строки

var="a b c"
first_loop=1
for i in $var
do
   (( $first_loop )) &&  # "((...))" is bash specific
   p="$i"            ||  # First -> Set
   p="$p"$'\n'"$i"       # After -> Append
   unset first_loop
done
echo "$p"                # No need -e

Используя функцию

embed_newline()
{
   local p="$1"
   shift
   for i in "[email protected]"
   do
      p="$p"$'\n'"$i"    # Append
   done
   echo "$p"             # No need -e
}

var="a b c"
p=$( embed_newline $var )  # Do not use double quotes "$var"
echo "$p"

Вывод одинаков для всех

a
b
c

Особая благодарность вкладчикам этого ответа: kevinf, Гордон Дэвиссон, l0b0, Dolda2000 и tripleee.


ИЗМЕНИТЬ

Ответ 2

Тривиальное решение состоит в том, чтобы поместить эти новые строки там, где вы хотите.

var="a
b
c"

Да, это назначение, заключенное в несколько строк.

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

echo "$p"

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

Ответ 3

Попробуйте echo $'a\nb'.

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

var=$'a\nb\nc'
echo "$var"

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

var="a b c"
for i in $var; do
    p="`echo -e "$p\\n$i"`"
done
echo "$p"

Ответ 4

Существует три уровня, на которых новая строка может быть вставлена ​​в переменную.
Ну... технически четыре, но первые два - это всего лишь два способа написать новую строку в коде.

1.1. При создании.

Самое главное - создать переменную с новыми символами уже. Мы пишем значение переменной в коде с уже вставленными новыми строками.

$ var="a
> b
> c"
$ echo "$var"
a
b
c

Или внутри кода script:

var="a
b
c"

Да, это означает запись Enter, где это необходимо в коде.

1.2. Создайте с помощью цитирования оболочки.

Последовательность $ ' является специальным расширением оболочки в bash и zsh.

var=$'a\nb\nc'

Линия анализируется оболочкой и расширяется до "var =" a newline b newline c "", что и есть то, что мы хотим, чтобы переменная var была. Это будет не работать с более старыми оболочками.

2. Использование расширений оболочки.

В основном это расширение команды с несколькими командами:

  • echo -e

    var="$( echo -e "a\nb\nc" )"
    
  • bash и zsh printf '% b'

    var="$( printf '%b' "a\nb\nc" )"
    
  • bash printf -v

    printf -v var '%b' "a\nb\nc"
    
  • Обычный простой printf (работает на большинстве оболочек):

    var="$( printf 'a\nb\nc' )"
    

3. Использование оболочки.

Все команды, перечисленные во втором параметре, могут использоваться для расширения значения var, если этот var содержит специальные символы.
Итак, все, что нам нужно сделать, это получить эти значения внутри var и выполнить некоторую команду, чтобы показать:

var="a\nb\nc"                 # var will contain the characters \n not a newline.

echo -e "$var"                # use echo.
printf "%b" "$var"            # use bash %b in printf.
printf "$var"                 # use plain printf.

Обратите внимание, что printf несколько небезопасно, если значение var контролируется злоумышленником.

Ответ 5

нет необходимости использовать для цикла

вы можете воспользоваться функциями расширения bash:

var="a b c"; 
var=${var// /\\n}; 
echo -e $var
a
b
c

или просто используйте tr:

var="a b c"
echo $var | tr " " "\n"
a
b
c

Ответ 6

sed решение:

echo "a b c" | sed 's/ \+/\n/g'

Результат:

a
b
c

Ответ 7

var="a b c"
for i in $var
do
   p=`echo -e "$p"'\n'$i`
done
echo "$p"

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