У меня есть следующие строки в PHP-скрипте:
$onecount=exec('grep -oi "STRING1" FILE1 | wc -l');
$boo=$onecount;
echo($boo);
exec("sed -i 1,20s/STRING2/$boo/ FILE2");
Когда я выполняю эту программу, она отображает число 27, которое является правильным значением для $onecount (и, следовательно, для $boo), т. е. количества раз, когда STRING1 встречается в FILE1. Поэтому я ожидаю, что все экземпляры STRING2 в первых 20 строках FILE2 будут заменены на «27». На самом деле ничего не меняется.
НО:
Когда я меняю вторую строку выше с
$boo=$onecount;
сказать,
$boo=3;
тогда все работает так, как ожидалось: программа отображает число 3 И правильно заменяет все экземпляры STRING2 в ФАЙЛЕ2 на строку «3».
Тот факт, что все работает так, как ожидалось, когда я устанавливаю $boo=3, говорит мне (я думаю), что с синтаксисом моей команды sed проблем нет.
Еще одна вещь, которая не сработала: я пробовал заменить $onecount такими вещами, как strvalue($onecount), но проблема не устранена.
Что мне не хватает?
Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Поскольку сейчас написано, трудно точно сказать, о чем вы спрашиваете.
@jhnc: Теперь, когда я понимаю (и успешно реализовал ответ Майки), мне кажется удивительным, что вы не смогли повторить это, и было бы интересно понять, почему. Но я не думаю, что у меня есть силы, чтобы попытаться понять это в данный момент.
Freebsd (и, вероятно, Macos), похоже, следуют стилю System V, а не posix и форматируют wc -l вывод, например %7u , тогда как coreutils использует %1u , а busybox использует %u
когда я пытаюсь exec("sed 1,20s/STRING2/ 5/ /dev/null"); php печатает сообщение об ошибке sed на stderr. Вы отбрасывали stderr? Странно, что вы не видели этого сообщения.
ваш код и ответ содержат уязвимости внедрения оболочки. вы могли бы рассмотреть escapeshellarg вместо передачи пустых аргументов или аргументов в одинарных кавычках
@jhnc: Я дилетант, а не программист. Я пишу код (используя vi) в окне терминала и запускаю этот код в браузере. Я даже не знал, где искать сообщения об ошибках от sed, хотя предполагаю, что увидел бы их, если бы запустил код из командной строки....но в любом случае ошибки я не увидел сообщение и не понял, что мне нужно его поискать.






Поэтому я ожидаю, что все экземпляры STRING2 в первых 20 строках FILE2 будут заменены на «27».
Если это так, то вам следует вызвать trim на выходе вашей первой exec команды:
$onecount = exec('grep -oi "STRING1" FILE1 | wc -l');
$boo = trim($onecount);
В противном случае в начале строки будут пробелы:
var_dump($boo)
->
string(8) " 27"
Как вы можете видеть, в начале этой строки есть пробельные символы, которые, похоже, вам не нужны.
На самом деле это причина, по которой ваш скрипт работает, когда вы вручную устанавливаете $boo на 3 - пробелы в начале приводят к сбою запуска sed, выдавая такое сообщение:
sed: 1: "1,20s/STRING2/": unterminated substitute in regular expression
Чтобы предотвратить эту проблему в случае, если вы действительно хотели иметь пробелы в начале, необходимо обернуть регулярное выражение апострофами:
exec("sed -i '1,20s/STRING2/$boo/' FILE2");
Или, если вы используете Mac:
exec("sed -i -e '1,20s/STRING2/$boo/' FILE2");
Если мы сложим это вместе, это даст мне:
<?php
$onecount = exec('grep -oi "STRING1" FILE1 | wc -l');
$boo = trim($onecount);
var_dump($boo);
exec("sed -i '1,20s/STRING2/$boo/' FILE2");
# for mac - see: https://stackoverflow.com/a/19457213/3080207
//exec("sed -i -e '1,20s/STRING2/$boo/' FILE2");
Кажется, это соответствует замыслу, если я хочу понять ваш первоначальный вопрос.
Это сработало. Я бы никогда не подумал об этом и через миллион лет. Огромное спасибо.
Я не могу повторить это с php 8.1 - используя файлы, содержащие именно эти строки, и запуская ваш точный код, изменение вносится.