Выполнение sed из php-скрипта

У меня есть следующие строки в 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), но проблема не устранена.

Что мне не хватает?

Я не могу повторить это с php 8.1 - используя файлы, содержащие именно эти строки, и запуская ваш точный код, изменение вносится.

jhnc 28.03.2024 08:51

Пожалуйста, уточните вашу конкретную проблему или предоставьте дополнительную информацию, чтобы выделить именно то, что вам нужно. Поскольку сейчас написано, трудно точно сказать, о чем вы спрашиваете.

Community 28.03.2024 11:10

@jhnc: Теперь, когда я понимаю (и успешно реализовал ответ Майки), мне кажется удивительным, что вы не смогли повторить это, и было бы интересно понять, почему. Но я не думаю, что у меня есть силы, чтобы попытаться понять это в данный момент.

WillO 28.03.2024 15:58

Freebsd (и, вероятно, Macos), похоже, следуют стилю System V, а не posix и форматируют wc -l вывод, например %7u , тогда как coreutils использует %1u , а busybox использует %u

jhnc 28.03.2024 17:21

когда я пытаюсь exec("sed 1,20s/STRING2/ 5/ /dev/null"); php печатает сообщение об ошибке sed на stderr. Вы отбрасывали stderr? Странно, что вы не видели этого сообщения.

jhnc 28.03.2024 17:27

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

jhnc 28.03.2024 17:45

@jhnc: Я дилетант, а не программист. Я пишу код (используя vi) в окне терминала и запускаю этот код в браузере. Я даже не знал, где искать сообщения об ошибках от sed, хотя предполагаю, что увидел бы их, если бы запустил код из командной строки....но в любом случае ошибки я не увидел сообщение и не понял, что мне нужно его поискать.

WillO 28.03.2024 22:05
Стоит ли изучать PHP в 2026-2027 годах?
Стоит ли изучать PHP в 2026-2027 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Symfony Station Communiqué - 7 июля 2023 г
Symfony Station Communiqué - 7 июля 2023 г
Это коммюнике первоначально появилось на Symfony Station .
Оживление вашего приложения Laravel: Понимание режима обслуживания
Оживление вашего приложения Laravel: Понимание режима обслуживания
Здравствуйте, разработчики! В сегодняшней статье мы рассмотрим важный аспект управления приложениями, который часто упускается из виду в суете...
Установка и настройка Nginx и PHP на Ubuntu-сервере
Установка и настройка Nginx и PHP на Ubuntu-сервере
В этот раз я сделаю руководство по установке и настройке nginx и php на Ubuntu OS.
Коллекции в Laravel более простым способом
Коллекции в Laravel более простым способом
Привет, читатели, сегодня мы узнаем о коллекциях. В Laravel коллекции - это способ манипулировать массивами и играть с массивами данных. Благодаря...
Как установить PHP на Mac
Как установить PHP на Mac
PHP - это популярный язык программирования, который используется для разработки веб-приложений. Если вы используете Mac и хотите разрабатывать...
0
7
54
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Поэтому я ожидаю, что все экземпляры 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");

Кажется, это соответствует замыслу, если я хочу понять ваш первоначальный вопрос.

Это сработало. Я бы никогда не подумал об этом и через миллион лет. Огромное спасибо.

WillO 28.03.2024 15:31

Другие вопросы по теме