Форум русскоязычного сообщества Ubuntu


Считаете, что Ubuntu недостаточно дружелюбна к новичкам?
Помогите создать новое Руководство для новичков!

Автор Тема: Вопрос по bash: $(...) усекает пустые строки в конце. Как исправить?  (Прочитано 984 раз)

0 Пользователей и 1 Гость просматривают эту тему.

Оффлайн ChapaikinVA

  • Автор темы
  • Любитель
  • *
  • Сообщений: 59
    • Просмотр профиля
[Ситуация]

Пример 1:
a="$(echo $'\n\n\n\n\n')"; echo ${#a};
0

Пример 2:
a="$(echo $'\n\n\n\n\n_')"; echo ${#a};
6

[Проблема/Вопрос]

Как переписать в «Примере 1» присваивание переменной a так, чтобы были сохранены все пустые строки в конце?
Желательно, наиболее простое решение.
Естественно, имеется в виду, что нужно присвоить не заранее известное значение, а вывод вызова какой-л. команды, причём присваивание д. корректно работать всегда (для любого вызова любой команды). Пример приведён намеренно упрощённый.


[Решение]

Помогли на др. сайте. На тек. момент наиболее подходящим из найденных (по моим критериям) явл. решение (знаете лучше - допишите):

to()
{
local to=${1};

IFS= read -rd '' ${to};
printf -v ${to} "${!to%$'\n'}";
};



# a="$(echo $'\n\n\n\n\n')"; # Неправильное присваивание

to a < <(echo $'\n\n\n\n\n'); # Правильное присваивание

А для общего случая:

to()
{
local to=${1};

IFS= read -rd '' ${to};
printf -v ${to} "${!to%$'\n'}";
};


# aVariable="$(some_command arg_1 … arg_n)"; # Неправильно
to aVariable < <(some_command arg_1 … arg_n); # Правильно

Функция to зд. - только для удобства и сокращения текста; в прот. случае, м. было бы каждый раз писать соотв. вызов read.
« Последнее редактирование: 30 Сентября 2014, 09:03:05 от ChapaikinVA »
Xenial xerus (белочка): пришла к разработчикам, а глюки теперь видят пользователи. WTF??!

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
L~$
L~$ a="$(echo $'\n\n\n\n\n_')"; echo ${a} | wc -c;
2
L~$ a="$(echo $'\n\n\n\n\n')"; echo ${a} | wc -c;
1
L~$

?
Wars ~.o

Оффлайн ChapaikinVA

  • Автор темы
  • Любитель
  • *
  • Сообщений: 59
    • Просмотр профиля
L~$
L~$ a="$(echo $'\n\n\n\n\n_')"; echo ${a} | wc -c;
2
L~$ a="$(echo $'\n\n\n\n\n')"; echo ${a} | wc -c;
1
L~$

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

П.С.

"?" - потому, что echo добавляет (по умолч.) в конце $'\n' (т.е., пустую строку).
a="$(echo $'\n\n\n\n\n')"; echo -n ${a} | wc -c;
0

П.П.С.

Кроме того, использование wc -с вообще м. быть некорректно (в общем случае), т. к. она считает кол-во байт, а не символов:
echo -n "ё" |  wc -c
2
echo -n "z" |  wc -c
1
« Последнее редактирование: 28 Сентября 2014, 09:29:53 от ChapaikinVA »
Xenial xerus (белочка): пришла к разработчикам, а глюки теперь видят пользователи. WTF??!

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
ChapaikinVA,
Цитировать
2
мобилка смс?
Wars ~.o

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Cтранно как-то у Вас всё, в простом какие-то сложности нашли…a="




" ; echo ${#a}
5
a="\n\n\n\n\n" ; echo "${#a}"
10
a='\n\n\n\n\n' ; echo "${#a}"
10
a=$'\n\n\n\n\n' ; echo "${#a}"
5
a=^M^M^M^M^M ; echo "${#a}"
5
здесь каждая «^M» это «Ctrl+V, Ctrl+M»a="\x0a\x0a\x0a\x0a\x0a" ; echo "${#a}"
20
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ChapaikinVA

  • Автор темы
  • Любитель
  • *
  • Сообщений: 59
    • Просмотр профиля
Cтранно как-то у Вас всё, в простом какие-то сложности нашли…
Я, может, непонятно вопрос поставил. Нужно присвоить не заранее известное значение, а вывод вызова какой-л. команды, причём (естественно), он м. быть каждый раз - разным, а присваивание д. корректно работать всегда.
« Последнее редактирование: 28 Сентября 2014, 11:44:15 от ChapaikinVA »
Xenial xerus (белочка): пришла к разработчикам, а глюки теперь видят пользователи. WTF??!

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
to aVariable < <(some_command arg_1 … arg_n); # Правильно
Работать не будет, так как дело всё в создании функции
to() { IFS= read -rd '' ${1}; };
Объясняю: FS (field separator == разделитель полей) установлен системой как [:space:], т.е. пробел, табуляция, перевод строки… Т.е. при обработке идущие подряд заменяются принимаются как 1 (а если полей нет(значащих символов), так и вообще как 0). Выхода два
  • изменить FS, чтобы Ваши переводы строк не обрабатывались как разделитель
  • "экранировать" разделитель, чтобы он не воспринимался как спецсимвол (стандартная процедура при присваивании)
Ещё бы объяснили с какой целью Вам это надо — возможно всё решается гораздо проще.
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

Оффлайн ChapaikinVA

  • Автор темы
  • Любитель
  • *
  • Сообщений: 59
    • Просмотр профиля
to aVariable < <(some_command arg_1 … arg_n); # Правильно
Работать не будет, так как дело всё в создании функции
А что именно должно не работать? Если пример сможете привести, где не работает - вообще здорово было бы.

Функция объявляется в самом начале скрипта, а ниже - она вызывается (функция зд. - только для удобства и сокращения текста; в прот. случае, м. было бы каждый раз писать соотв. вызов read). Т.к. я пробую - вроде пока нормально. Поясните, пожалуйста. Про IFS могли не объяснять (это есть в man bash).
« Последнее редактирование: 28 Сентября 2014, 12:42:50 от ChapaikinVA »
Xenial xerus (белочка): пришла к разработчикам, а глюки теперь видят пользователи. WTF??!

Оффлайн victor00000

  • Старожил
  • *
  • Сообщений: 15568
  • Глухонемой (Deaf)
    • Просмотр профиля
L~$
L~$ ( read -t 0 && echo "== `cat` ==" )
L~$ ( read -t 0 && echo "== `cat` ==" )
L~$ ( read -t 0 && echo "== `cat` ==" ) <<< 1
== 1 ==
L~$
L~$ ( read -t 0 && echo "== `cat` ==" ) <<< 1
== 1 ==
L~$ ( read -t 0 && echo "== `cat` ==" ) <<< 1
== 1 ==
L~$
L~$ echo 1 | ( read -t 0 && echo "== `cat` ==" )
== 1 ==
L~$ echo 1 | ( read -t 0 && echo "== `cat` ==" )
== 1 ==
L~$ ( read -t 0 && echo "== `cat` ==" ) <<< 1
== 1 ==
L~$ ( read -t 0 && echo "== `cat` ==" )
L~$ ( read -t 0 && echo "== `cat` ==" )
L~$
L~$ cat
^C
L~$

Wars ~.o

Оффлайн Azure

  • Модератор раздела
  • Старожил
  • *
  • Сообщений: 6017
  • Windows10, i3wm on Debian9, Manjaro20.0
    • Просмотр профиля
Я имел ввиду то, что Вы написали только 1 строку и назвали именно её решением задачи. Одна строка не будет работать. Для корректного выполнения задачи нужно определение функции to() и именно оно (назначение функции) и есть решение.
В общем случае если Вам нужны строки, то решаться это может и через массивunset a i; while read ; do a[++i]="$REPLY" ; done < <(echo $'\n\n\n\n\n') ; echo ${#a[@]}
6 # +1 перевод строки самой команды echo
Кроме того многострочный вывод правильнее хранить не в переменной, а файлеt="/tmp/tmp.file"; echo $'\n\n\n\n\n' > $t ; cat $t | wc -l ; rm $t
6
« Последнее редактирование: 28 Сентября 2014, 14:16:41 от Azure »
В Линукс можно сделать ВСЁ что угодно, достаточно знать КАК !

 

Страница сгенерирована за 0.092 секунд. Запросов: 27.