Удалите последний знак из переменной эха

Я получаю ожидаемый результат. Первая команда печатает каждый объект дважды. Вторая команда печатает его однажды.

Это является довольно нетрадиционным - у "некоторых" будет значение нуля по умолчанию, так как это не определено. $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}'
5
04.01.2015, 00:18
8 ответов

Вам редко бывает нужен цикл bash:

echo {0..55..5} | sed 's/ /,/g'
10
27.01.2020, 20:31

Вместо того, чтобы везде добавлять запятые, а затем удалять последнюю, вот потенциальное решение "чистого баша" с использованием переменной 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
6
27.01.2020, 20:31

Более сложные решения, которые вы получили, лучше, но для полноты, вы всегда можете просто удалить последнюю запятую с помощью sed:

for ((i=1, j=0; i <= 12 ; i++, j=j+5))
do
 echo -n "$j,"
done | sed 's/,$//'
5
27.01.2020, 20:31

Вот решение, совместимое с 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.

.
5
27.01.2020, 20:31

Вы просто добавляете проверку, когда достигаете конца:

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
2
27.01.2020, 20:31

В 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 работает в вашем случае использования, я бы согласился с этим.

.
14
27.01.2020, 20:31

Для справки, с помощью zsh:

$ echo ${(j(,)):-{0..55..5}}
0,5,10,15,20,25,30,35,40,45,50,55
4
27.01.2020, 20:31

Удивительно, что никто не упомянул, чтобы просто написать обратное пространство в конце:

$ printf "%s" {0..55..5},; printf "\b"
0,5,10,15,20,25,30,35,40,45,50,55
3
27.01.2020, 20:31

Теги

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