LINUX.ORG.RU

CHR='?'
N=10
{ seq 1 $N | tr -dc \\n | tr \\n "$CHR"; echo; }

dilmah ★★★★★
()
Ответ на: комментарий от Cy6erBr4in

> Как ты представляешь себе это без цикла?

в перле есть оператор x: можно написать ('?' x 10)

мое решение тоже в принципе можно сказать без цикла

это что, мне на одном собеседовании сказали вывести числа 1..N без цикла -- я стал ему на шаблонах делать, а собеседующий имел в виду рекурсию:)

dilmah ★★★★★
()
Ответ на: комментарий от Cy6erBr4in

> Как ты представляешь себе это без цикла?

$ function do_x { if [ $1 -gt 0 ]; then do_x  $(($1 - 1)) "$2$3" $3 ; else echo $2; fi  }
$ function X { do_x $1 "" $2; }
$ X 10 "x"
xxxxxxxxxx
$ X 12 "foobar"
foobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobarfoobar

Ы? ;-)

anonymous
()
Ответ на: комментарий от Laz

>ESC N CHR

Это в интерактивном режиме. А так - цикл.

Laz ★★★★★
()
Ответ на: комментарий от anonymous

это рекурсия...

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

Cy6erBr4in ★★★
()
Ответ на: комментарий от anonymous

Родил вот это для выравнивания строки в поле определённой длины:
str2fld () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
local i
if [ $str_l -eq $fld_l ]; then
echo -n "$str"
elif [ $str_l -le $fld_l ]; then
[ "$fld_a" = 'l' ] && echo -n "$str"
for ((i=0; i<$((fld_l-str_l)); i++)); do echo -n $fld_f; done
[ "$fld_a" = 'r' ] && echo -n "$str"
else
if [ "$fld_a" = 'l' ]; then
echo -n "${str:0:$fld_l}"
else
echo -n "${str:$((str_l-fld_l)):$fld_l}"
fi
fi
}

Вроде не соответствует принципу KISS, мне кажется, через $(printf ...) было бы проще (?).

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

> Родил вот это для выравнивания строки в поле определённой длины:

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

dilmah ★★★★★
()

printf "%${N}s" ' ' | sed "s/ /$CHR/g"

Недостатки:
* Не работает для N==0.
* Не работает для CHR=='/' ну и наверное еще каких-нибудь.

rymis ★★
()
Ответ на: комментарий от rymis

О, спасибо огромное тебе, rymis, это как раз то, что и нужно было.
Сейчас переписал код функции, теперь он выглядит так:

str2fld () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
local l_just=
 if     [ $str_l -eq $fld_l ]; then
  echo -n "$str"
 elif   [ $str_l -le $fld_l ]; then
  [ "$fld_a" = 'l' ]  && l_just='-'
  printf "%${l_just}${fld_l}s" "$str"
 else
  if [ "$fld_a" = 'l' ]; then
   echo -n "${str:0:$fld_l}"
  else
   echo -n "${str:$((str_l-fld_l)):$fld_l}"
  fi
 fi
}

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от rymis

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

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от dilmah

Ребяты, меня только что осенило!
Вот, что нужно сделать, куда уж короче-то :)

str2fld_x () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
 if [ $fld_a = 'l' ]; then
  echo -n "${str}`echo -e '\t' | expand -t $fld_l | sed \"s% %${fld_f}%g\"`" | cut -b1-${fld_l}
 else
  echo -n "`echo -e '\t' | expand -t $fld_l | sed \"s% %${fld_f}%g\"`${str}" | rev | cut -b1-${fld_l} | rev
 fi
 return 0
}

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Варианты с использованием Perl и PHP не принимаются: здесь даже awk был бы несколько перебором, а вы хотите вообще самостоятельные языки программирования привлечь для решения в общем-то элементарной задачи!

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

>а вы хотите вообще самостоятельные языки программирования привлечь для решения в общем-то элементарной задачи!

Вызов perl'ового варианта осуществляется c:
real 0m0.004s
user 0m0.000s
sys 0m0.002s

неужто так плохо?

Или неужто есть что-то заметно короче?

...

А то скоро будет как в той присказке, «Настоящий линуксоид за 3 часа напишет программу, которая за 5 секунд сделает то, что обычный пользователь руками делал бы полчаса.»

:)

KRoN73 ★★★★★
()
Ответ на: комментарий от DRVTiny

>Кстати, мой второй вариант хотя и короче в разы, работает ощутимо медленнее :(

В смысле perl vs PHP? У меня наоборот, перловый быстрее в несколько раз оказался.

KRoN73 ★★★★★
()
Ответ на: комментарий от KRoN73

Да нет же, я о двух опубликованных выше вариантах функции выравнивания и обрезания строки в поле фиксированной длины!

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

1-Й ВАРИАНТ (ДЛИННЫЙ, НО ОТНОСИТЕЛЬНО БЫСТРЫЙ)
str2fld () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
local i=0
local l_just=
 if     [ $str_l -eq $fld_l ]; then
  echo -n "$str"
 elif   [ $str_l -le $fld_l ]; then
  if [ "$fld_f" = ' ' ]; then
   [ "$fld_a" = 'l' ]  && l_just='-'
   printf "%${l_just}${fld_l}s" "$str"
  else
   [ "$fld_a" = 'l' ] && echo -n "$str"
   for ((; i<$((fld_l-str_l)); i++)); do echo -n $fld_f; done
   [ "$fld_a" = 'r' ] && echo -n "$str"
  fi
 else
  if [ "$fld_a" = 'l' ]; then
   echo -n "${str:0:$fld_l}"
  else
   echo -n "${str:$((str_l-fld_l)):$fld_l}"
  fi
 fi
}

2-Й ВАРИАНТ (КОРОТКИЙ, НО МЕДЛЕННЫЙ):
str2fld_x () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
 if [ $fld_a = 'l' ]; then
  echo -n "${str}`echo -e '\t' | expand -t $fld_l | sed \"s% %${fld_f}%g\"`" | cut -b1-${fld_l}
 else
  echo -n "`echo -e '\t' | expand -t $fld_l | sed \"s% %${fld_f}%g\"`${str}" | rev | cut -b1-${fld_l} | rev
 fi
 return 0
}

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

напиши четкую спецификацию -- ну или хотя бы пример приведи как функция выравнивания должна работать

dilmah ★★★★★
()
Ответ на: комментарий от dilmah

Есть строка, положим, это
s='12345678'
Необходимо дополнить её до 10-ти символов нулями, соответственно:
N=10
f='0'
Или, если строка длиннее десяти символов, обрезать её.
Видим, что задача делится на две: строку можно пирдвинуть к левому краю фиксированного поля, а можно - к правому. И, соответственно, можно обрезать её с правого конца, а можно - с левого.
Соответственно, может быть a='l' (выравнивание по левому краю/обрезание справа) и a='r' (выравнивание по правому краю/обрезание слева)

Вот эту-то высокоинтеллектуальную задачу, не сравнимую ни с какими там,понимаешь, разложениями функций в ряд Фурье, и решает моя скромная функция в двух своих ипостасях - короткой и длинной соответственно.
Примеры вызова функции str2fld приведены ниже:

str2fld '12345678' 10 '0' 'l'
str2fld '1234567890ABCDEF' 10 '0' 'r'

И т.д.

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от fghj

И что это решает, какую проблему? Может, я чего-то недопонимаю? А если в качестве символа-заполнителя используется не ноль, а буква 'Х', тогда что?

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

Вот вариант с добавленным выравниванием по центру (m):
str2fld () {
local str="$1"
local str_l=${#str}
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
local l_just=
 if     [ $str_l -eq $fld_l ]; then
  echo -n "$str"
 elif   [ $str_l -le $fld_l ]; then
  if [ "$fld_f" = ' ' ]; then
   [ "$fld_a" = 'l' ]  && l_just='-'
   printf "%${l_just}${fld_l}s" "$str"
  else
   if [ $fld_a = 'm' ]; then
    fld_l_d2=$(((fld_l-str_l)>>1))
    for ((i=0; i<$fld_l_d2; i++)); do echo -n $fld_f; done
    echo -n "$str"
    for ((i=0; i<$((fld_l-fld_l_d2-str_l)); i++)); do echo -n $fld_f; done
   else
    [ "$fld_a" = 'l' ] && echo -n "$str"
    for ((i=0; i<$((fld_l-str_l)); i++)); do echo -n $fld_f; done
    [ "$fld_a" = 'r' ] && echo -n "$str"
   fi
  fi
 else
  case $fld_a in
  l)
   echo -n "${str:0:$fld_l}"
  ;;
  r)
   echo -n "${str:$((str_l-fld_l)):$fld_l}"
  ;;
  m)
   echo -n "${str:$(((str_l-fld_l)>>1)):$fld_l}"
  ;;
  esac
 fi
}                                      

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

>И что это решает, какую проблему? Может, я чего-то недопонимаю? А если в качестве >символа-заполнителя используется не ноль, а буква 'Х', тогда что?

кто использует не ноль bash?

fghj ★★★★★
()
Ответ на: комментарий от DRVTiny

Может проще будет сгенерить строку из символов заполнителей заведомо достаточной длины --- не менее ширины поля, хоть задать в скрипте B="XXXXXXXXXXXX", хоть с помощью A=`printf "%10s" " "`; B=${A//?/X}), а потом выводить нужное количество символов echo ${B:0:$((str_l-fld_l))} ...

mky ★★★★★
()
Ответ на: комментарий от fghj

На самом деле по моим наблюдениям скрипт на чистом BASH без использования вызовов сторонних программ (а printf к таким относится) без особой на то надобности - будет работать в разы быстрее. Подтверждением тому - которотенькая функция str2fld_x, которая почти в 10 раз медленнее своего длиннющего прототипа:

str2fld_x () {
local str="$1"
local fld_l=$2
local fld_f=${3:0:1}
local fld_a=${4:0:1}
 if [ $fld_a = 'l' ]; then
  echo -n "${str}`printf \"%.${fld_l}d\" '0' | sed \"s%0%${fld_f}%g\"`" | cut -b1-${fld_l}
 else
  echo -n "`printf \"%.${fld_l}d\" '0' | sed \"s%0%${fld_f}%g\"`${str}" | rev | cut -b1-${fld_l} | rev
 fi
 return 0
}

DRVTiny ★★★★★
() автор топика
Ответ на: комментарий от DRVTiny

>На самом деле по моим наблюдениям скрипт на чистом BASH без >использования вызовов сторонних программ (а printf к таким относится)

вообще-то printf эта встроенная (builtin) функция bash

fghj ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.