Для наблюдения uuid раздела жесткого диска, я просто загружаю систему с CD Linux и goto, который мой компьютер монтирует, нажимает, раздел, который я хочу видеть. uuid количество раздела Linux будет отображено.
Можно также видеть диск uuid путем выполнения Дисковой утилиты Linux после того, как CD Linux загрузится.
Просто добавьте символ *
к переменной 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. Вот полное руководство. Это раздел о циклических конструкциях.
Ответ 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
вариант позволяет повторять текст любой длины.)
POSIXly:
$ n=5 awk 'BEGIN{OFS="*";for(i=2;i<=ENVIRON["n"]+1;i++){$i="";print}}'
Во-первых, вот некоторые временные сравнения некоторых других предлагаемых решений:
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
*
**