Mal wieder REGEX

Fragen zu allen Themen rund ums Programmieren außerhalb von phpBB können hier gestellt werden - auch zu anderen Programmiersprachen oder Software wie Webservern und Editoren.
Antworten
Benutzeravatar
mad-manne
Ehemaliges Teammitglied
Beiträge: 5403
Registriert: 18.03.2005 10:00
Wohnort: Marl im Ruhrgebiet

Mal wieder REGEX

Beitrag von mad-manne »

Hallo zusammen,
ich mal wieder mit einer REGEX-Frage :D

Ich durchsuche Zeilen eines Scripts, um dort genutzt Funktionsaufrufe für lokalisierte Termini zu finden und diese zu extrahieren.
Diese Aufrufe sehen immer so aus

Code: Alles auswählen

LEERZEICHEN + t('Hier steht dann beliebiger Text, den ich finden will .... bis hier >')
Ich will also den Text zwischen den Hochkommata(ergo den Parameter) des Funktionsaufrufs der Funktion t
Das klappt auch schon mit dieser REGEX:

Code: Alles auswählen

(?<=t\(')(.*)(?='\))
In diesem Beispiel wird Language-string I want to extract gefunden:

Code: Alles auswählen

<?= $this->form->checkbox('foo', t('Language-string I want to extract'), 1, $values['foo'] == 1) ?>
Leider treten in einer Zeile aber auch mal 2 oder noch mehr Aufrufe dieser t-Funktion auf ... dann finde ich leider alles bis zum Ende des letzten Funktionsaufrufes .. .siehe hier:

Code: Alles auswählen

<?= $this->form->checkbox('foo', t('Language-string I want to extract'), 1, t('Second function-call in the same line')$values['foo'] == 1) ?>
findet dann natürlich das hier: Language-string I want to extract'), 1, t('Second function-call in the same line

Irgendwie müsste also REGEX so lauten:
Finde alles bis zum NÄCHSTEN vorkommen von ') ... und dann suche weitere Vorkommen.

Geht das und wenn JA .. wie ?
Try not. Do or do not. There is no try. (YODA)
Supportanfragen via E-Mail oder PN werden ignoriert
Benutzeravatar
Dr.Death
Moderator
Moderator
Beiträge: 17395
Registriert: 23.04.2003 08:22
Wohnort: Xanten
Kontaktdaten:

Re: Mal wieder REGEX

Beitrag von Dr.Death »

Aus dem Bauch heraus:

Den (.*) auf nicht gierig umstellen: (.*?)

Code: Alles auswählen

(?<=t\(')(.*?)(?='\))
findet dann aus: <?= $this->form->checkbox('foo', t('Language-string I want to extract'), 1, $values['foo'] == 1) ?>
folgendes:

<?= $this->form->checkbox('foo', t('Language-string I want to extract'), 1, t('Second function-call in the same line')$values['foo'] == 1) ?>

Den ersten kann man ja in $1 packen und der nächste wird in $2, §3 usw. sein.

Demo: https://regex101.com
Benutzeravatar
mad-manne
Ehemaliges Teammitglied
Beiträge: 5403
Registriert: 18.03.2005 10:00
Wohnort: Marl im Ruhrgebiet

Re: Mal wieder REGEX

Beitrag von mad-manne »

Hey Doc,
das ist vermutlich nur die halbe Lösung ...

Mit deiner REGEX findet er jetzt korrekterweise wieder Language-string I want to extract aber danach ist dann Schluss
Vermutlich muss dieser Ausdruck dann noch in eine "Schleife", um JEDES passende Pattern zu extrahieren... nur wie ??

Ich bin ja schon stolz wie Bolle, dass ich (übrigens auch auf regex101.com) die erste Lösung selbst gefunden hatte :grin:

LG,
Manne

EDIT: Ooops ... ich hatte zwischenzeitlich auf regex101 die Parameter g und m deaktiviert ... NUN geht's :D
Doc ... du bist der BESTE !
Try not. Do or do not. There is no try. (YODA)
Supportanfragen via E-Mail oder PN werden ignoriert
Benutzeravatar
mad-manne
Ehemaliges Teammitglied
Beiträge: 5403
Registriert: 18.03.2005 10:00
Wohnort: Marl im Ruhrgebiet

Re: Mal wieder REGEX

Beitrag von mad-manne »

Hmmm ... leider gibt es noch 2 Probleme (eins davon habe ich schon gelöst)

Ich hatte vergessen, dass es natürlich auch Aufrufe mit Parametern gibt so wie hier:

Code: Alles auswählen

        <?= t('New due-date: %s for the task "%s". Are you sure?', $task['confirm_pushed_date_due'], $task['title']) ?>
Also suche ich jetzt nicht mehr bis ') sondern nur noch bis '
REGEX dafür = (?<= t\(\')(.*?)(?=\')

ABER nun habe ich(hoffentlich) das letzte offene Problem, da es natürlich auch Strings mit einem ESCAPTEN Hochkomma gibt wie hier:

Code: Alles auswählen

    <h2><?= t('Push the task\'s due-date') ?></h2>
Und davon "bekomme" ich natürlich nur Push the task\ zurück anstatt Push the task\'s due-date :(

Ich müsste also REGEX sagen, dass es bis zum nächsten Vorkommen eines Hochkomma matchen soll, aber NUR, wenn dieses Hochkomma keinen Backslash davor hat.

Geht das auch noch ??
EDIT: Hier könnte man es testen https://regex101.com/r/IMnxZZ/1/

Freue mich über Feedback,
Manne
Try not. Do or do not. There is no try. (YODA)
Supportanfragen via E-Mail oder PN werden ignoriert
Benutzeravatar
Dr.Death
Moderator
Moderator
Beiträge: 17395
Registriert: 23.04.2003 08:22
Wohnort: Xanten
Kontaktdaten:

Re: Mal wieder REGEX

Beitrag von Dr.Death »

(?<= t\(\')(.*?[^\\])(?=\')


Im (.*?) hab ich ein: [^\\] hinzugefügt. --> (.*?[^\\])

Result:
<?= t('New due-date: %s for the task "%s". Are you sure?', $task['confirm_pushed_date_due'], $task['title']) ?>
<h2><?= t('Push the task\'s due-date') ?></h2>
Demo: https://regex101.com/r/QvTVs7/1
Benutzeravatar
mad-manne
Ehemaliges Teammitglied
Beiträge: 5403
Registriert: 18.03.2005 10:00
Wohnort: Marl im Ruhrgebiet

Re: Mal wieder REGEX

Beitrag von mad-manne »

Du bist mein HELD :geek:

Code: Alles auswählen

/**
 * Return an array of language-keys used in the given script
 *
 * @param string $script_file Script to search for calls to the translate-function t('foo')
 *
 * @return array
 */
function getScriptKeys($script_file) {
    $lang_keys = array();
    $lang_keys['script_file'] = $script_file;
    $all_lang_keys['lang_keys'] = array();
    // REGEXpression to find language-keys
    $regx_find_lang_keys = '/(?<= t\(\')(.*?[^\\\\])(?=\')/m';  // Thanks to DrDeath :-D ( https://github.com/DrDeath )

    $handle = @fopen($script_file, "r");

    ... / ...
EDIT: Ach sieh an ... du bist(natürlich) auch auf github ... gleich mal den DANK verlinkt :wink:

Mich findet man dort unter einem anderen Nickname
Try not. Do or do not. There is no try. (YODA)
Supportanfragen via E-Mail oder PN werden ignoriert
Antworten

Zurück zu „Coding & Technik“