Я получаю ожидаемый результат. Первая команда печатает каждый объект дважды. Вторая команда печатает его однажды.
Это является довольно нетрадиционным - у "некоторых" будет значение нуля по умолчанию, так как это не определено. $some - поэтому 0$, который представляет всю строку, так в основном Вы заменяете строку тем, что Вы находите в 2$, когда Вы используете $some=$2
Сравните его с этим результатом:
johan@computer:~$ df|awk '{$some=$2; print}'
1K-blocks
30827524
4041028
1621692
5120
4054228
102400
4054228
60555340
209548784
Почему был бы Вы не получать вывод или другой результат: Я ожидаю, что поведение использования непосвященных переменных будет потенциально не определено, по крайней мере, в некоторых системах.
На Солярисе у меня есть доступ к "стандарту" awk, а также, предположительно, POSIX совместимая версия, установленная в/usr/xpg4/bin/awk. Оба из них приводят к тому же результату для следующего
Они приводят к переменным результатам в зависимости от того, добавляю ли я печать "привет" впереди или нет, и в зависимости от того, заменяю ли я последнюю команду "печатью" (в земельном участке $some печати) или нет.
Все они печатают ЧТО-ТО, не пробелы, хотя - мне не удалось найти версию, которая воспроизводит тот эффект.
Таким образом, я ожидаю, что это будет некоторым неопределенным поведением из-за использования неинициализированной переменной - Вы присваиваете значение столбцу, который потенциально далеко проходит конец возможного диапазона столбцов во входном потоке. $some обращается к столбцу, определенному значением "некоторых"
Необходимо просто использовать "некоторых" в качестве переменной, например,
df | awk '{print "hello";some=$2; print some}'
Вместо того, чтобы везде добавлять запятые, а затем удалять последнюю, вот потенциальное решение "чистого баша" с использованием переменной IFS
с формой расширения массива [*]
a=( {0..55..5} ); (IFS=, ; printf '%s\n' "${a[*]}")
0,5,10,15,20,25,30,35,40,45,50,55
Смотрите BashGuide/Arrays для подробностей - в том числе для объяснения использования (. ...)
для сохранения значения родительской оболочки IFS
.
Если вы не хотите использовать подход с использованием массива, то вы можете избежать использования внешней команды sed
, используя встроенные возможности подстановки строк в оболочке, например (опять же в bash)
printf -v str '%s,' {0..55..5}; printf '%s\n' "${str%,}"
0,5,10,15,20,25,30,35,40,45,50,55
Более сложные решения, которые вы получили, лучше, но для полноты, вы всегда можете просто удалить последнюю запятую с помощью sed
:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
echo -n "$j,"
done | sed 's/,$//'
Вот решение, совместимое с POSIX:
i=-5
until [ $((i=i+5)) -eq 55 ]
do printf ${i},
done && echo $i
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
В качестве альтернативы можно манипулировать IFS:
set -- $(echo $((i=0)); until (exit $((i-55))); do echo $((i=i+5)); done)
IFS=,
echo "$*"
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
Но...
unset IFS
printf %s\\n "$@"
###OUTPUT###
0
5
10
15
20
25
30
35
40
45
50
55
Все приращения все еще доступны в $@
и по отдельности доступны в $1
- ${12}
.
И это весело и без петли:
i= ; eval echo $(IFS=0; printf '${i:+,}$((i=i${i:++5}))%s' $(printf %012d))
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
С bc
и tr
:
echo '0;while(a+=5<=55){",";a}'|bc|tr -d \\n
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
или просто bc
и оболочкой...
printf %s $(echo '0;while(a+=5<=55){",";a}'|bc)
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
С GNU dc
:
dc -e '[pq]sq0[rdn[,]P5+d55=qrdx]dx'
###OUTPUT###
0,5,10,15,20,25,30,35,40,45,50,55
мне нравится последнее лучшее, но я сосунок для уродливого сценария dc
.
Вы просто добавляете проверку, когда достигаете конца:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
if [[ $i -ne 12 ]]
then
echo -n "$j,"
else
echo -n "$j"
fi
done
В GNU и некоторых других системах, для этой конкретной проблемы, просто используйте seq
:
seq -s, 0 5 55
, что дает последовательность от 0 до 55 (включительно), разделенную запятой.
Есть несколько вариантов чистого доступа, которые могут быть полезны, если ваша проблема немного сложнее, чем предполагается в примере. Наибольшим стандартом является использование эксплицитного теста для определения, находитесь ли вы на последней итерации:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
echo -n "$j"
[ $i -lt 12 ] && echo -n ,
done
Здесь мы только распечатываем $j
каждый раз, и проверяем, не составляет ли $i
меньше 12 (т.е, Мы не находимся на последней итерации) перед тем, как распечатать запятую.
Альтернативой является построение всего вывода в виде одной строки:
for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
ACCUM="$ACCUM$j,"
done
echo "${ACCUM%,}"
Здесь мы делаем ACCUM
удерживающим то же самое, что вы уже распечатывали, но мы ничего не выводим в самом цикле. Вы можете обрезать запятую в конце с помощью ${ACCUM%,}
: это увеличивает значение ACCUM
до , при этом все, что совпадает с ,
обрезается.
Если опция seq
работает в вашем случае использования, я бы согласился с этим.
Для справки, с помощью zsh
:
$ echo ${(j(,)):-{0..55..5}}
0,5,10,15,20,25,30,35,40,45,50,55
Удивительно, что никто не упомянул, чтобы просто написать обратное пространство в конце:
$ printf "%s" {0..55..5},; printf "\b"
0,5,10,15,20,25,30,35,40,45,50,55