Это мой первый вопрос о StackOverflow. :)
Я работаю с файлом Excel, мне нужно дублировать формулы в каждой строке, поэтому мне нужно менять индексы строк в этих формулах для каждой новой строки. Для этого я написал регулярное выражение, чтобы уловить индекс строки листа в формуле, исключая другие цифры, не относящиеся к индексу строки (например: «=2024-17-04») и исключая имя листа, имеющее цифры (например: «MATMAS05») .
Это работает очень хорошо, за исключением части «исключение имени листа, имеющего цифры».
Я написал это регулярное выражение: [A-Z]((?!MATMAS05)|(?<!"))+(\d+)(?!")
.
И у меня есть примеры формул, в которых индекс строки, который нужно поймать, равен 5:
SI(F5 = "";"";"Z_PACK_TYPE")
MARKET!A5
MARKET!MQ5
MARKET!AB5
MARKET!TX5
MARKET!SX5
MATMAS05!CZ5 = "3200";MARKET!DA5
SI(MATMAS05!CZ5 = "3200";MATMAS05!CZ5 = "3200";MARKET!DA5;"")
SI(L5 = "";"";"STRING")
SI(MATMAS05!CZ5 = "3300";MARKET!DA5;"")
SI(ESTVIDE(MARKET!EG5);"";SI(MATMAS05!CZ5 = "3200";MARKET!EG5;""))
Чтобы проверить свое регулярное выражение, я создал сохранение regex101, которым делюсь с вами соответствующим regex101.
Но, как вы можете видеть, мое регулярное выражение также улавливает цифру «5» в имени моего листа «MATMAS05».
Я хотел бы исключить имя листа «MATMAS05» из моих уловов.
Знаете ли вы, чего не хватает в моем регулярном выражении для этой цели?
Если внутри кавычек есть ложные срабатывания, в 99,9% случаев вам может сойти с рук "[^"]*(?:""[^"]*)*"|![A-Z]+(\d+)
@WiktorStribiżew Я забыл добавить еще один пример формулы, внутри которого нет имени листа. В этом случае ![A-Z]+(\d+)
не работает.
Попробуйте regex101.com/r/PHCBkF/6, значение группы 1 — это то, что вам нужно.
Это странно, потому что кажется, что оно работает хорошо, когда я смотрю на регулярное выражение101, но я пробую его на PHP-коде с предварительным совпадением, скрипт не всегда находит номер индекса строки. Вы можете увидеть это в этом онлайн-сохраненном скрипте onlinephp.io/c/c2fd6 Хорошо обрабатываются только формулы без имен листов, в остальных случаях функция preg_match возвращает только имя листа. Ты знаешь почему?
Итак, вы делаете это на PHP, отлично. Попробуйте $regex = '/(?:(?<!")(?:"")*"[^"]*(?:""[^"]*)*"|\w+!)(*SKIP)(*F)|\b[A-Z]+\K\d+\b/';
, если вам нужно вернуть только цифры. Если вам нужно получить ВСЕ совпадения, используйте preg_match_all($regex, $formula, $matches);
Посмотрите эту скрипку.
Это то, что вы ищете: https://regex101.com/r/W99ncx/1 ?
@Dunois С помощью этого регулярного выражения ячейка L5 ( SI(L5 = "";"";"Z_LIFE_CYCLE_SG") не перехватывается. Мне нужно заранее поймать индекс строки с именем листа и без него, чтобы увеличить его в формуле для моей следующей строки.
А моя рабочий пример? Вы это видели?
@NicolasC, тогда просто сделайте регулярное выражение более конкретным, например: https://regex101.com/r/anTyqH/1 . Если CZ5
в SI(MATMAS05!CZ5 = "3200";MATMAS05!CZ5 = "3200";MARKET!DA5;"")
также необходимо захватить вместе с DA5
, используйте что-то вроде этого: https://regex101.com/r/ThbdM7/1 .
Пожалуйста, также посмотрите решение @WiktorStribiżew. Он реализован в PHP
и, похоже, делает именно то, что вам нужно.
Вы можете использовать
<?php
// Enter your code here, enjoy!
$formulas = [
'SI(F5 = "";"";"Z_PACK_TYPE")',
'MARKET!A5',
'MARKET!MQ5',
'MARKET!AB5',
'MARKET!TX5',
'MARKET!SX5',
'MATMAS05!CZ5 = "3200";MARKET!DA5',
'SI(MATMAS05!CZ5 = "3200";MATMAS05!CZ5 = "3200";MARKET!DA5;"")',
'SI(L5 = "";"";"STRING")',
'SI(MATMAS05!CZ5 = "3300";MARKET!DA5;"")',
'SI(ESTVIDE(MARKET!EG5);"";SI(MATMAS05!CZ5 = "3200";MARKET!EG5;""))',
];
$regex = '/(?:(?<!")(?:"")*"[^"]*(?:""[^"]*)*"|\w+!)(*SKIP)(*F)|\b[A-Z]+\K\d+\b/';
foreach ($formulas as $formula) {
preg_match_all($regex, $formula, $matches);
var_dump($matches);
}
Посмотрите демонстрацию PHP.
Регулярное выражение
(?:(?<!")(?:"")*"[^"]*(?:""[^"]*)*"|\w+!)(*SKIP)(*F)|\b[A-Z]+\K\d+\b
Посмотрите демонстрацию регулярных выражений . Подробности:
Подробности:
(?:(?<!")(?:"")*"[^"]*(?:""[^"]*)*"|\w+!)(*SKIP)(*F)
- совпадения и пропуски:
(?<!")(?:"")*"[^"]*(?:""[^"]*)*"
— подстрока между двумя символами "
с экранированной кавычкой "
внутри|
- или\w+!
— один или несколько символов слова, а затем символ !
.|
- или\b[A-Z]+\K\d+\b
— граница слова, одна или несколько заглавных букв ASCII, \K
опускает совпадающие символы, а затем сопоставляются и используются одна или несколько цифр, за которыми следует граница слова.Спасибо @wiktor-stribiżew. Ваша формула работает идеально. 👌 Спасибо за быструю и эффективную помощь.🙏
Я думаю, вам просто нужно
![A-Z]+(\d+)
, см. regex101.com/r/PHCBkF/4. Если все ваши ссылки содержат имена листов, это сработает.