Detecteren van spatie, witregel en enter
Voor een script gebruikte ik deze expressie om spatie(s), witregel(s) en enter(s) in een blok tekst te detecteren:
Kwam er echter achter dat sommige type spaties toch niet gedetecteerd werden.
Deze expressie lijkt alles wel te detecteren:
Mijn vraag is, mis ik misschien toch wat?
Guido
Wel over de eerste.
Laat ik die omschrijven naar
\s+|ab|a|b
nemen we het woord "absoluut"
eerste term zoekt naar spaties, dat doet nu niet terzake.
De tweede zoekt naar "ab" en ja, dat komt voor.
de derde zoekt naar "a", en hé diezelfde A aan het begin van het woord matcht.
Idem voor de "b" om op te zoeken.
Met andere woorden: als je op \r en \n afzonderlijk zoekt, hoef je niet op de combinatie van beide ook nog te zoeken.
Bedankt. Ik ging er van uit dat hij de hele term moest matchen.
En omdat \r, \n en \r\n afzonderlijk gebruikt worden, had ik ze alle drie toegevoegd. Maar dat hoeft dus blijkbaar niet niet.
Guido
Toevoeging op 10/06/2024 20:06:34:
Quote:
ik heb geen opmerking over je laatste expressie.
Bedoel je hiermee dat deze expressie de lading dekt?
Guido
Bedoel je misschien "\n" en "\r" ? Of wil je ook tabs meetellen?
Zelf ben ik niet zo van regex, het kan zijn dat het veel sneller werkt dan dezelfde code in PHP:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
/// Controleert of tekenreeks witruimte bevat
/// spaties, en enters zijn US-ASCII en uitwisselbaar met Unicode
/// @param string $s Te controleren tekenreeks
/// @return bool true bij witruimte, anders false
function heeft_witruimte(string $s) : bool {
for ($i = 0, $l = strlen($s); $i < $l; $i++) {
switch ($s[$i]) {
case ' ':
case "\r":
case "\n":
return true;
}
}
return false;
} // fn heeft_witruimte
var_dump(heeft_witruimte("E\u{00E9}n tekenreeks\u{0020}met enter\r\nen spaties.")); // true
var_dump(heeft_witruimte("E\u{00E9}ntekenreeksmetenterenspaties.")); // false
?>
/// Controleert of tekenreeks witruimte bevat
/// spaties, en enters zijn US-ASCII en uitwisselbaar met Unicode
/// @param string $s Te controleren tekenreeks
/// @return bool true bij witruimte, anders false
function heeft_witruimte(string $s) : bool {
for ($i = 0, $l = strlen($s); $i < $l; $i++) {
switch ($s[$i]) {
case ' ':
case "\r":
case "\n":
return true;
}
}
return false;
} // fn heeft_witruimte
var_dump(heeft_witruimte("E\u{00E9}n tekenreeks\u{0020}met enter\r\nen spaties.")); // true
var_dump(heeft_witruimte("E\u{00E9}ntekenreeksmetenterenspaties.")); // false
?>
Ikzelf vind de code in PHP leesbaarder en eenvoudiger te onderhouden.
Je ziet in één oogopslag wat het doet, en als je bijvoorbeeld tabs wilt kan je het lijstje makkelijk uitbreiden met "\t".
Ter info:
Het is mijn bedoeling om van een tekst die spaties, witregels, tabs, enters, etc bevat 1 lange regel te maken (met behoud van 1 spatie tussen elk woord).
Zodat ik er daarna een nette array van kan maken, die geen lege waarden bevat.
De array gebruik ik ten slotte om hier bepaalde woorden uit te halen en te tellen.
Code (php)
1
2
3
2
3
$tekst = 'Mijn tekst die spaties, witregels, tabs, enters, etc bevat';
$opgeschoonde_tekst = preg_replace('/\s+/u', ' ', $tekst);
$array = explode(' ', $opgeschoonde_tekst);
$opgeschoonde_tekst = preg_replace('/\s+/u', ' ', $tekst);
$array = explode(' ', $opgeschoonde_tekst);
Ik zie nu dat mijn explode() functie een enter/nieuwe regel hetzelfde behandelt als een spatie. Dus daarom heb ik \r\n uit de regex gehaald.
De spatie laat ik in de regex staan.
Kwam er namelijk achter dat als er een HTML spatie (tag) tussen meerdere woorden staat, deze woorden als 1 waarde in de array terechtkomen. Dit gebeurde bij een copy-pasted tekst, die dus HTML opmaak bevatte.
Gewijzigd op 11/06/2024 17:09:01 door Guido -
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
2
3
4
5
6
7
8
9
10
11
12
<?php
$tekst = "De tekenreeks met een enter\r\nen een of meer spaties.";
$bepaald = ['de', 'het', 'een']; // woorden om te tellen
$telling = [];
const PHP_STR_WORD_COUNT_ARRAY = 1; // je moet ook alles zelf doen..
foreach (str_word_count($tekst, PHP_STR_WORD_COUNT_ARRAY) as $w) {
$woord = strtolower($w); // letterkastongevoelig
if (!in_array($woord, $bepaald)) { continue; }
$telling[$woord]++;
}
var_dump($telling); // resultaat ["de" => 1, "een" => 2]
?>
$tekst = "De tekenreeks met een enter\r\nen een of meer spaties.";
$bepaald = ['de', 'het', 'een']; // woorden om te tellen
$telling = [];
const PHP_STR_WORD_COUNT_ARRAY = 1; // je moet ook alles zelf doen..
foreach (str_word_count($tekst, PHP_STR_WORD_COUNT_ARRAY) as $w) {
$woord = strtolower($w); // letterkastongevoelig
if (!in_array($woord, $bepaald)) { continue; }
$telling[$woord]++;
}
var_dump($telling); // resultaat ["de" => 1, "een" => 2]
?>
Er zit wel een groot "Ja maar, nee!" aan deze code; het werkt niet met Unicode.
Wil je dat toch omdat je bijvoorbeeld met HTML5 werkt, of wat iemand uit een Word-document plakt, dan:
- kan je een bestaande lexer gebruiken van bijvoorbeeld Parle (slecht gedocumenteerd)
- kan je een eigen lexer schrijven (is makkelijker)
- kan je mb_substr_count() gebruiken in een for-lus (makkelijkst, maar slechtste performance)
Quote:
Er zit wel een groot "Ja maar, nee!" aan deze code; het werkt niet met Unicode.
Mijn manier werkt eigenlijk ook prima nu.
Nu ik de regex aangepast heb genereert de explode() een array zonder overbodige lege waarden en spaties in waarden.
Mijn manier is qua performance misschien niet super snel, maar ach, zal vast slechts milliseconden zijn..
Guido
Gewijzigd op 12/06/2024 21:50:06 door Guido -
Met regex is ook prima toch? Dat ik het niet snap wil niet zeggen dan het niet goed is :)