Оук или Сед: Если паттерн найден: удалить строку && экспортировать переменную

Итак, @StephaneChazelas правильно меня поправляет в комментариях ниже - сама оболочка никоим образом не диктует максимальный размер аргумента, разрешенный вашей системой, а скорее он установлен вашим ядром.

Как уже говорили некоторые другие, кажется, что ядро ​​ограничивает 128 Кбайт максимальным размером аргумента, который вы можете передать новому процессу из любого другого при его первом запуске. Эта проблема возникает, в частности, из-за множества вложенных подоболочек $ (подстановка команд) , которые должны выполняться на месте и передавать весь свой вывод от одной к другой.

И это своего рода дикая догадка, но поскольку несоответствие ~ 5 КБ кажется настолько близким к стандартному размеру системной страницы, я подозреваю, что она предназначена для страницы, которую bash использует для обработки подоболочки. ваш $ (подстановка команд) требует, чтобы в конечном итоге доставил свой вывод и / или стек функций, который он использует для связывания вашей таблицы массива с вашими данными. Могу только предположить, что ни то, ни другое не дается бесплатно.

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

Для этого я в основном использовал трубы. Но я также оценил массив оболочки в здесь-документе , указывающем на стандартный ввод cat. Результаты ниже.

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

time bash <<-\CMD
    ( for arg in `seq 1 6533` ; do
        printf 'args+=(' ; printf b%.0b `seq 1 6533` ; echo ')'
    done ;
    for arg in `seq 1 6533` ; do
        printf %s\\n printf\ '%s\\n'\ \""\${args[$arg]}"\" ;
    done ) | . /dev/stdin >&2
CMD
bash <<<''  66.19s user 3.75s system 84% cpu 1:22.65 total

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

Я попытался изменить часть генератора printf во второй строке на:

printf \ b%.0b

Он также работает:

bash <<<''  123.78s user 5.42s system 91% cpu 2:20.53 total

Так что, может быть, я немного болен. Я использую заполнение нулями здесь и добавляю в предыдущем значение «$ arg» к текущему значению «$ arg» . Я выхожу за пределы 6500 ...

time bash <<-\CMD
    ( for arg in `seq 1 33` ; do
        echo $arg >&2
        printf 'args+=('"${args[$((a=arg-1))]}$(printf "%0${arg}0d" \
            `seq 1 6533` ; printf $((arg-1)))"')\n'
    done ;
    for arg in `seq 1 33` ; do
        printf '/usr/bin/cat <<HERE\n%s\nHERE\n' "\${args[$arg]}"
    done ) | . /dev/stdin >&2
CMD

bash <<<''  14.08s user 2.45s system 94% cpu 17.492 total

И если я изменю строку cat , чтобы она выглядела так:

printf '/usr/bin/cat <<HERE | { printf '$arg'\  ; wc -c ;}
    %s\nHERE\n' "\${args[$arg]}"

Я могу получить количество байтов из wc. Помните, что это размеры каждого ключа в массиве args . Общий размер массива - это сумма всех этих значений.

1 130662
2 195992
3 261322
4 326652
5 391982
6 457312
7 522642
8 587972
9 653302
10 718633
11 783963
12 849293
13 914623
14 979953
15 1045283
16 1110613
17 1175943
18 1241273
19 1306603
20 1371933
21 1437263
22 1502593
23 1567923
24 1633253
25 1698583
26 1763913
27 1829243
28 1894573
29 1959903
30 2025233
31 2090563
32 2155893
33 2221223
1
03.12.2018, 00:59
2 ответа

Вам нужно каким-то образом экспортировать информацию из части awk. Либо вы можете экспортировать переменную, либо использовать статус выхода .

awk -i inplace 'BEGIN {err = 1}; {if (NR == 1 && /([[:space:]]|^)debug: Debug([[:space:]]|$)/) {err = 0} else {print}}; END {exit err}' ${SourceP} && export Debug=Debug

Пояснение

  • BEGIN {err = 1}:первоначально установите статус ошибки на 1.
  • Затем, если вы находитесь в первой строке NR == 1и &&в этой строке есть /([[:space:]]|^)debug: Debug([[:space:]]|$)/, установите статус ошибки на 0(err = 0). В противном случае напечатайте все остальные строки. Это регулярное выражение debug: Debugначинается либо с пробела, либо с начала строки и заканчивается либо пробелом, либо концом строки.
  • Когда сценарий awkзавершится, выйдите со статусом ошибки {exit err}.
  • Следовательно, если /debug: Debug/будет найдено в файле, статус ошибки будет равен 0 и &&будет запущено.
1
27.01.2020, 23:31
test "$(sed -i -e '/debug: Debug/{w /dev/fd/1' -e 'd}' "$SourceP")" && export Debug=Debug

Примечания:

Письмо ${SourceP}— чистый маньеризм; это так же опасно, как и простое $SourceP. Вы хотите указать вместо:"$SourceP"или "${SourceP}".

/dev/fd/1поддерживается большинством современных Unix-систем; sed -iи awk -iспецифичны для GNU и крайне непереносимы.

1
27.01.2020, 23:31

Теги

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