Я должен инкапсулировать awk переменные в кавычках для очистки их?

  • df метаданные файловой системы отчетов - т.е. что файловая система способна к хранению в данный момент. Важная вещь отметить состоит в том, что в некоторых файловых системах это должно не обязательно отразить свободное пространство (это - свободное место, хотя), так как фс может сделать предварительные выделения, когда это думает, что это - хорошая идея (например, XFS может сделать это, когда Вы начнете создавать большой файл - это выделит дополнительное место, чтобы гарантировать, что файл менее рассеивается и не проводит слишком много времени с выделениями, когда это должно будет записать фактические данные в диск). Такое пространство отмечено как доступное с некоторой задержкой. Информация также отражает факт, что некоторое пространство на диске (или мог бы быть), необходимый структурам файловой системы - это может вызвать любопытный эффект на некоторые файловые системы: создание отчетов о больше чем 100% располагает использование с интервалами.

  • du даст Вам реальное использование диска с гранулярностью блоков файловой системы (в большинстве систем, не уверенных в тех, которые могут использовать один блок для данных нескольких файлов). Так как это имеет к stat() каждый файл, принадлежащий главной иерархии каталогов (та du дан на командной строке), это медленно, специально для случаев с маленькими файлами.

  • stat даст Вам информацию о единственном файле (или каталог в этом отношении).

Следовательно, если Вы хотите знать:

  • сколько свободного пространства Вы имеете в файловой системе (приблизительно), использовать df;

  • сколько данных Вы действительно имеете в файлах (не обязательно в единственной файловой системе), использовать du - знайте, что это может легко стать медленным особенно в некоторых сетевых файловых системах;

  • сколько места запись для самого корневого каталога занимает, использовать stat / .

7
23.05.2017, 14:33
3 ответа

Эти два примера демонстрируют различие:

$ echo _TMP_ | awk -v VAR='some "text"' '{ gsub(/_TMP_/, VAR) ; print }'
some "text"
$ echo _TMP_ | awk -v VAR='some "text"' '{ gsub(/_TMP_/, "VAR") ; print }'
VAR

Когда VAR закрывается кавычки, awk обработки это как переменная со значением some "text". Когда VAR внутренние кавычки, awk рассматривает его как три символьных строки.

Еще: bash имеет проблемы очистки. Рассмотрите:

$ VAR="rm important_file" ; $VAR

Вышеупомянутое сотрется important_file. Таким образом, bash похож на макроязык: это заменит переменную и затем попытается выполнить результат. awk отличается. Рассмотрите:

$ echo _TMP_ | awk -v VAR='var); print $1' '{ gsub(/_TMP_/, VAR) ; print }'
var); print $1

awk обработки VAR как простой текст, не как потенциальные команды для выполнения.

Проблемы могут возникнуть, однако, если Вы позволяете bash измените awk сценарий. В моих примерах выше, awk сценарии были всеми в одинарных кавычках. Это предотвращает bash от питания с ними.

5
27.01.2020, 20:17
  • 1
    VAR='blah; echo $1' не проблема к оболочке ни один (если Вы не используете eval). Это не макроязык (кроме в некоторой степени wrt расширение псевдонима) –  Stéphane Chazelas 06.02.2014, 11:28

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

Существует несколько вещей рассмотреть здесь.

заключение в кавычки переменных оболочки

Отъезд переменной закрыл кавычки в оболочках POSIX (в контекстах списка, как в аргументах команде), нет awk, split+glob оператор.

Если Вы делаете:

cmd foo=$var

Где $var * *.

Tha't, просящий, чтобы оболочка разделяла содержание $var на основе значения $IFS специальная переменная оболочки, по умолчанию на пробелах. Таким образом выше, который дает нам foo=* и * и выполните globbing на каждом из тех, который является, расширяются foo=* ко всем именам файлов в текущем каталоге, которые запускаются с foo= и * ко всем нескрытым именам файлов.

Так, действительно, необходимо почти всегда заключать переменные оболочки в кавычки, являются ли они аргументами awk или нет. Это также применяется к замене команды оболочки (`...` и $(...)) и окружите арифметическое расширение ($((...))).

передающие данные как есть к awk

Другая проблема - это awk (не оболочка), разворачивает escape-последовательности обратной косой черты в присвоениях переменных как -v var=value (и с GNU awk 4.2 или выше, если значение запускается с @/ и концы в /, это рассматривают как regexp тип переменной).

Например, -v var='\n/\n/' устанавливает содержание awk var переменная к <newline>/<newline>/, нет \n/\n/. Это также относится awk переменные определяются как:

awk '...' var=value

Передать данные awk без него подвергающийся тому расширению, можно использовать ENVIRON или ARGV массивы awk:

var=$value awk 'BEGIN {var=ENVIRON["var"]} ...'

(выше, это - присвоение переменной оболочки (к непеременной типа массив), таким образом, не может быть split+glob, который является одним из редких случаев, где можно опустить кавычки вокруг переменных),

или:

awk 'BEGIN {var=ARGV[1]; delete ARGV[1]} ...' "$value"

заключение в кавычки и awk переменные

Это split+glob является только оболочкой (неправильная) функция. awk язык является совершенно другим языком.

В awk, переменные отнесены в a varname, нет $varname и кавычки используются для представления строк. Так "varname" varname строка, в то время как varname относится к переменной.

очистка переменных для предотвращения инжекции кода

Строго говоря заключение в кавычки переменных оболочки не санирует, оно не заключает переменные в кавычки, который использует split+glob оператор. На большинстве языков при помещении кавычек вокруг фиксированных строк, в оболочках, это наоборот: каждой вещью является строка, и кавычки используются для предотвращения некоторого специального поведения, и особенно переменные должны почти всегда заключаться в кавычки (плохое проектное решение такой имевший смысл в Оболочке Bourne в 70-х, но помеха в современных оболочках, zsh будучи единственной оболочкой, которая частично зафиксировала это).

Оболочка или awk не оценят/интерпретируют код, сохраненный в их собственной переменной, если Вы не скажете им.

var='foo; rm -f var'
echo $var
# or
echo "$var"

Не заставит содержание переменной быть оцененным как код оболочки (хотя первый подвергнется разделению и globbing, который может иметь страшные последствия (например, с var='/*/*/*/*/../../../../*/*/*/*/../../../../*/*/*/*'). Вам было бы нужно:

eval "echo $var"
# or
sh -c "echo $var"

чтобы это было оценено/интерпретировано как код оболочки.

awk не имеет такого eval функция. perl/python сделать.

Но остерегайтесь перекрестного загрязнения. У Вас могут быть данные переменной передачи оболочки (в переменных оболочки) как код для выполнения awk:

awk '{print "'"$var"': " $0}'

было бы опасно в случае, если $var переменная оболочки содержит, например:

var='test"; print "foo" > /etc/passwd; print "blah'

потому что оболочка затем выполнилась бы:

["awk", "{print \"test\"; print \"foo\" > /etc/passwd; print \"blah: \" $0}"]

Или наоборот:

awk '{system("echo foo: " $0)}' < file

где awk выполнил бы оболочку как:

["sh", "-c", "echo foo: content-of-the-line"]

для каждой строки file (и думайте что строка как ; rm -rf / сделал бы).

Это не только между awk и sh. Необходимо быть осторожными каждый раз, когда переменные/неконтролируемые данные могут быть оценены как код другим интерпретатором. Примеры:

sed "s/$regexp/blah/g"

sedязык ограничен, но он может все еще для нанесения вреда, как с regexp='//;w /etc/passwd; s/'.

Или:

find . -exec sh -c "echo {}" \;

Теперь, для предотвращения тех проблем существует два общих подхода:

  1. преобразуйте переменную от одного интерпретатора до другого. Это работает на оболочку-> awk, или найдите-> sh случай выше. Как изменение:

    awk '{print "'"$var"': " $0}'
    

    кому:

    awk -v awk_var="$var" '{print awk_var ": " $0}'
    

    И:

    find . -exec sh -c "echo {}" \;
    

    кому:

    find . -exec sh -c 'echo "$1"' sh {} \;
    

    но это не будет работать на оболочку-> sed, или awk-> случаи оболочки.

  2. когда 1 не возможно, необходимо санировать переменные, чтобы или удалить или выйти из символов, которые могут быть проблемой. В,

    awk '{system("echo foo: " $0)}'
    

    необходимо преобразовать $0 к чему-то, что является чистой строкой насколько затронута оболочка. Одна опция состоит в том, чтобы снабдить префиксом каждый символ обратную косую черту, но это не будет работать на новую строку (не проблема здесь). Другой должен включить строку в одинарные кавычки и выйти из каждой одинарной кавычки.

    awk 'function escape(s) {
           gsub(/'\''/,"&\\\\&&",s)
           return "'\''" s "'\''"
         }
         {system("echo foo: " escape($0))}'
    
4
27.01.2020, 20:17
  • 1
    Спасибо, это - большая информация. Я все еще немного смущен на "безопасности" раздавания материала как этот. В моем случае я ДЕЙСТВИТЕЛЬНО хочу, чтобы это расширилось, но я не хочу, чтобы это нанесло ущерб. В целях обсуждения, скажем, что значение переменной оболочки $SOURCEIP rm -fr /. Если я передаю это awk через awk -v AWKVAREXAMPLE="$SOURCEIP" и затем позже имейте awk, делают gsub как gsub(/^_TARGETSTRING_/, AWKVAREXAMPLE); это в конечном счете "просочилось" бы в оболочку и уничтожило бы все? –  Mike B 06.02.2014, 10:16
  • 2
    @MikeB, нет. Это просочилось бы к оболочке если awk вызванный оболочка и передал это как код для него для интерпретации как в: awk '{system("echo " var)}' (где var ;rm -rf /), где awk вызовы ["sh", "-c", "echo; rm -rf /"] или awk '{print | "tr " v1 " " v2}' где awk передает вывод по каналу к ["sh", "-c", "tr content-of-v1 content-of-v2"]. вещи –  Stéphane Chazelas 06.02.2014, 10:41
  • 3
    , которых Вы хотите избежать, похожи: awk "{print \"$shell_variables\"}" как там, содержание переменной оболочки интерпретируется как awk код. –  Stéphane Chazelas 06.02.2014, 10:43

Если вы передаете Awk переменной в систему , вам нужно указать ее в оболочке:

function quote(str,   d, m, x, y, z) {
  d = "\47"; m = split(str, x, d)
  for (y in x) z = z d x[y] d (y < m ? "\\" d : "")
  return z
}

Пример:

system(sprintf("ffmpeg -i %s outfile.m4a", quote(ARGV[1])))

Источник

0
27.01.2020, 20:17

Теги

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