Как создать последовательность циклов?

Для наблюдения uuid раздела жесткого диска, я просто загружаю систему с CD Linux и goto, который мой компьютер монтирует, нажимает, раздел, который я хочу видеть. uuid количество раздела Linux будет отображено.

Можно также видеть диск uuid путем выполнения Дисковой утилиты Linux после того, как CD Linux загрузится.

5
09.06.2015, 01:39
4 ответа

Просто добавьте символ * к переменной a вместо счетчика цикла:

for i in {1..5}
do
  a+='*'
  echo "${a}"
done

Обратите внимание, что a = "$ {a} *" вместо a + = '*' работает так же хорошо, но я думаю, что версия + = более аккуратная / понятная.

Если вы хотите сделать это с помощью цикла while, вы можете сделать что-то вроде этого:

while (( "${#a}" < 5 )); do
  a+='*'
  echo "$a"
done

$ {# a} расширяется до длины строки в переменной a .

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

a=

Я предполагаю, что вы используете оболочку bash. Вот полное руководство. Это раздел о циклических конструкциях.

8
27.01.2020, 20:31

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

for i in {1..5}
do
  printf "%${i}s\n"
done | sed 's/ /*/g'

Здесь используется printf для вывода необходимого количества пробелов, затем sed для замены пробелов на символы, которые нам действительно нужны.

Как указано в Digital Trauma и Янис , вы можете сохранить результат printf в переменной и использовать замену подстроки оболочки, чтобы избежать использования sed (во многих случаях за счет создания множества подоболочек):

for i in {1..5}
do
  a=$(printf "%${i}s")
  echo "${a// /*}"
done

Кавычки необходимы с echo здесь, чтобы оболочка не интерпретировала символы * . Кроме того, с echo \ n больше не требуется.

Как указывает kojiro , tr больше подходит для замены одиночных символов, чем sed :

for i in {1..5}
do
  printf "%${i}s\n"
done | tr ' ' '*'

(Но sed вариант позволяет повторять текст любой длины.)

5
27.01.2020, 20:31

POSIXly:

$ n=5 awk 'BEGIN{OFS="*";for(i=2;i<=ENVIRON["n"]+1;i++){$i="";print}}'
4
27.01.2020, 20:31

Во-первых, вот некоторые временные сравнения некоторых других предлагаемых решений:

time \
    bash -c '
        for i in {1..1000}
        do    printf "%0${i}s\n"
        done| sed "y/ /*/"
'   >/dev/null

real    0m0.017s
user    0m0.023s
sys     0m0.000s

Это неплохо, хотя я добавил небольшую оптимизацию, используя y / / * / выражение перевода вместо оператора подстановки регулярного выражения s / / * / g .

time \
     bash -c '
     for i in {1..1000}
     do    a=$(printf "%0${i}s")
           echo "${a// /*}"
     done
'    >/dev/null

real    0m1.337s
user    0m0.723s
sys     0m0.187s

Вау. Это ужасно.

Вот один, который я бы посоветовал вам использовать, если вы действительно одержимы решением, основанным только на оболочке. Преимущество этого перед другими протестированными состоит в том, что, во-первых, не требуется устанавливать две переменные - когда-либо устанавливается только одна, это $ IFS , и это только один раз. Он также не выполняет ветвление дочерней оболочки за итерацию - что обычно не хорошая идея.

Он основан на механизме подстановки в $ * для полей в $ @ . Поэтому он просто добавляет новую нулевую позицию для каждой итерации. Также обратите внимание, что он избегает для {1..1000} расточительного расширения скобок.

time \
    bash -c '
        IFS=\*; set ""
        until [ "$#" -gt 1001 ]
        do    set "" "$@"
              echo  "$*"
        done
'   >/dev/null

real    0m0.755s
user    0m0.753s
sys     0m0.000s

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

Это немного лучше - дело обстоит наоборот. Вместо того, чтобы расширять "$ @" , чтобы получить нужные значения, он строит его экспоненциально и постепенно обрезает:

time \
    bash -c '
        set \*;n=0 IFS=
        until [ "$#" -gt 512 ]
        do    set "$@" "$@"
              shift "$(($#>1000?24:0))"
              until [ "$n" -eq "$#" ]
              do    printf %."$((n+=1))s\n" "$*"
        done; done
'   >/dev/null

real    0m0.158s
user    0m0.157s
sys     0m0.020s

Чтобы превзойти мое собственное предложение, касающееся только оболочки, на много, (по крайней мере, с bash - dash , выполнив указанное выше, и bash выполнив приведенное ниже - шея и шея) :

time \
    bash -c 'a=
        for i in {1..1000}
        do    a+=\*
              echo "$a"
        done
'   >/dev/null

real    0m0.020s
user    0m0.017s
sys     0m0.000s

- похоже, bash оптимизирует форму a + = , чтобы фактически выполнял добавление, а не полное повторное вычисление / повторное назначение. В любом случае, sed по-прежнему его превосходит.

sed выше не превосходит awk , хотя:

time \
    bash -c '
        n=1000 \
        awk "BEGIN{OFS=\"*\";for(i=2;i<=ENVIRON[\"n\"]+1;i++){\$i=\"\";print}}"
'   >/dev/null

real    0m0.010s
user    0m0.007s
sys     0m0.000s

... который пока самый быстрый.

Но никто не побьет другой sed , который выполняет в основном то же, что и моя nstars функция (вы найдете ее ниже) сделала бы, если бы вы сделали nstars 1000 :

time \
    bash -c '
        printf %01000s |
        sed -ne "H;x;:loop
             s/\(\n\)./*1/
             P;//t loop"
'   >/dev/null

real    0m0.007s
user    0m0.000s
sys     0m0.003s

... который пока самый быстрый. (при запуске с временем nstars 1000> / dev / null реальный результат был .006s ) . Подробнее об этом ниже.

Другое решение POSIX:

echo Type some stuff:
sed -ne 'H;x;:loop
    s/\(\n\)./*\1/
    P;//!q;t loop'

Вставьте вышеуказанное прямо в свой терминал, введите любую строку и нажмите Enter . Вы увидите пирамиду * s, по одной строке для каждого введенного вами символа. 3-символьная строка даст три строки, 4-символьная - 4 и т. Д.

sed прекрасно способен читать ввод tty и манипулировать им, как вам нравится. В этом случае он считывает строку от пользователя, помещает новую строку \ n в начало считанной строки, а затем рекурсивно заменяет строку \ n и символ, следующий сразу за это с * и \ n ewline снова, все время P полоскание только до \ n ewline каждый раз.

При этом пространство шаблонов на самом деле выглядит так (я просто заменил команду P rint на l ook) :

here's some stuff
*\nere's some stuff$
**\nre's some stuff$
***\ne's some stuff$
****\n's some stuff$
*****\ns some stuff$
******\n some stuff$
*******\nsome stuff$
********\nome stuff$
*********\nme stuff$
**********\ne stuff$
***********\n stuff$
************\nstuff$
*************\ntuff$
**************\nuff$
***************\nff$
****************\nf$
*****************\n$

верхняя строка была моим вкладом. Однако с P :

here's some stuff
*
**
***
****
*****
******
*******
********
*********
**********
***********
************
*************
**************
***************
****************
*****************

Если вы хотите остановить его, например, на 5, вы можете добавить тест /. \ {5 \} \ n / , например это:

echo Type some stuff:
sed -ne 'H;x;:loop
    s/\(\n\)./*\1/
    P;//!q;/.\{5\}\n/q
    t loop'

Вы можете сгенерировать строки таким же образом:

nstars()(  n=${1##*[!0-9]*}
           shift  "$((!!n))" 
           if   [ -n "${n:-$1}" ]
           then printf %0"$n"s "$*"
           else [ -t 0 ] &&
                echo Type some stuff: >&0
                head -n 1
           fi | sed -ne 'H;x;:loop
                     s/\(\n\)./*\1/
                     P;//t loop'
)

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

{   nstars 3
    nstars three
    echo 3please | nstars
    nstars
}

ВЫХОД:

*
**
***
*
**
***
****
*****
*
**
***
****
*****
******
*******
Type some stuff:
ok
*
**
2
27.01.2020, 20:31

Теги

Похожие вопросы