Newer
Older
7001
7002
7003
7004
7005
7006
7007
7008
7009
7010
7011
7012
7013
7014
7015
7016
7017
7018
7019
7020
7021
7022
7023
7024
7025
7026
7027
7028
7029
7030
7031
7032
7033
7034
7035
7036
7037
7038
7039
7040
7041
7042
7043
7044
7045
7046
7047
7048
7049
7050
7051
7052
7053
7054
7055
7056
7057
7058
7059
7060
7061
7062
7063
7064
7065
7066
7067
7068
7069
7070
7071
7072
7073
7074
7075
7076
7077
7078
7079
7080
7081
7082
7083
7084
7085
7086
7087
7088
7089
7090
7091
7092
7093
7094
7095
7096
7097
7098
7099
7100
7101
7102
7103
7104
7105
7106
7107
7108
7109
7110
7111
7112
7113
7114
7115
7116
7117
7118
7119
7120
7121
7122
7123
7124
7125
7126
7127
7128
7129
7130
7131
7132
7133
7134
7135
7136
7137
7138
7139
7140
7141
7142
7143
7144
7145
7146
7147
7148
7149
7150
7151
7152
7153
7154
7155
7156
7157
7158
7159
7160
7161
7162
7163
7164
7165
7166
7167
7168
7169
7170
7171
7172
7173
7174
7175
7176
7177
7178
7179
7180
7181
7182
7183
7184
7185
7186
7187
7188
7189
7190
7191
7192
7193
7194
7195
7196
7197
7198
7199
7200
7201
7202
7203
7204
7205
7206
7207
7208
7209
7210
7211
7212
7213
7214
7215
7216
7217
7218
7219
7220
7221
7222
7223
7224
7225
7226
7227
7228
7229
7230
7231
7232
7233
7234
7235
7236
7237
7238
7239
7240
7241
7242
7243
7244
7245
7246
7247
7248
7249
7250
7251
7252
7253
7254
7255
7256
7257
7258
7259
7260
7261
7262
7263
7264
7265
7266
7267
7268
7269
7270
7271
7272
7273
7274
7275
7276
7277
7278
7279
7280
7281
7282
7283
7284
7285
7286
7287
7288
7289
7290
7291
7292
7293
7294
7295
7296
7297
7298
7299
7300
7301
7302
7303
7304
7305
7306
7307
7308
7309
7310
7311
7312
7313
7314
7315
7316
7317
7318
7319
7320
7321
7322
7323
7324
7325
7326
7327
7328
7329
7330
7331
7332
7333
7334
7335
7336
7337
7338
7339
7340
7341
7342
7343
7344
7345
7346
7347
7348
7349
7350
7351
7352
7353
7354
7355
7356
7357
7358
7359
7360
7361
7362
7363
7364
7365
7366
7367
7368
7369
7370
7371
7372
7373
7374
7375
7376
7377
7378
7379
7380
7381
7382
7383
7384
7385
7386
7387
7388
7389
7390
<h4>Tags that contain “my-class” within their class attribute
value</h4>
<pre><(?:[^>"']|"[^"]*"|'[^']*')+></pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>^(?:[^>"']|"[^"]*"|'[^']*')+?\sclass\s*=\s*("[^"]*"|'[^']*')</pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>["'\s]my-class["'\s]</pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>(?:^|\s)my-class(?:\s|$)</pre>
<p>Regex options: None<br>
Regex flavors: .NET, Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h2>9.8. Add a cellspacing Attribute to <table> Tags That Do Not
Already Include It</h2>
<h3>Solution</h3>
<h4>Solution 1, simplistic</h4>
<pre><table\b(?![^>]*?\scellspacing\b)([^>]*)></pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre><table \b # Match "<table", as a complete word
(?! # Not followed by:
[^>]*? # Any attributes, etc.
\s cellspacing \b # "cellspacing", as a complete word
)
([^>]*) # Capture attributes, etc. to backreference 1
></pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h4>Solution 2, more reliable</h4>
<pre><table\b(?!(?:[^>"']|"[^"]*"|'[^']*')*?\scellspacing\b)((?:[^>"']|"[^"]*"|'[^']*')*)></pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre><table \b # Match "<table", as a complete word
(?! # Not followed by: Any attributes, etc., then "cellspacing"
(?:[^>"']|"[^"]*"|'[^']*')*?
\s cellspacing \b
)
( # Capture attributes, etc. to backreference 1
(?:[^>"']|"[^"]*"|'[^']*')*
)
></pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h4>Insert the new attribute</h4>
<pre><table cellspacing="0"$1></pre>
<pre><table cellspacing="0"\1></pre>
<h2>9.9. Remove XML-Style Comments</h2>
<h3>Solution</h3>
<pre><!--.*?--></pre>
<p>Regex options: Dot
matches line breaks<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<pre><!--[\s\S]*?--></pre>
<p>Regex options: None<br>
</p><h3>Discussion</h3>
<h4>When comments can’t be removed</h4>
<pre><(script|style|textarea|title|xmp)\b(?:[^>"']|"[^"]*"|'[^']*')*>.*?</\1\s*>|<plaintext\b(?:[^>"']|"[^"]*"|'[^']*')*>.*|<[a-z](?:[^>"']|"[^"]*"|'[^']*')*>|<!\[CDATA\[.*?]]></pre>
<p>Regex options: Case
insensitive, dot matches line breaks<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<pre># Special element: tag and its content
<( script | style | textarea | title | xmp )\b
(?:[^>"']|"[^"]*"|'[^']*')*
> .*? </\1\s*>
|
# <plaintext/> continues until the end of the string
<plaintext\b
(?:[^>"']|"[^"]*"|'[^']*')*
> .*
|
# Standard element: tag only
<[a-z] # Tag name initial character
(?:[^>"']|"[^"]*"|'[^']*')*
>
|
# CDATA section
<!\[CDATA\[ .*? ]]></pre>
<p>Regex options: Case
insensitive, dot matches line breaks, free-spacing<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<pre><(script|style|textarea|title|xmp)\b(?:[^>"']|"[^"]*"|'[^']*')*>[\s\S]*?</\1\s*>|<plaintext\b(?:[^>"']|"[^"]*"|'[^']*')*>[\s\S]*|<[a-z](?:[^>"']|"[^"]*"|'[^']*')*>|<!\[CDATA\[[\s\S]*?]]></pre>
<p>Regex options: Case
insensitive<br>
</p><h3>Variations</h3>
<h4>Find valid XML comments</h4>
<pre><!--[^-]*(?:-[^-]+)*--\s*></pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre><!--(?>-?[^-]+)*--\s*></pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, PCRE, Perl, Ruby</p>
<h4>Find valid HTML comments</h4>
<pre><!--(?!-?>)[^-]*(?:-[^-]+)*--></pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h2>9.10. Find Words Within XML-Style Comments</h2>
<h3>Problem</h3>
<pre> This "TODO" is not within a comment, but the next one is. <!--
TODO
: Come up with a cooler comment for this example. --></pre>
<h3>Solution</h3>
<h4>Two-step approach</h4>
<pre><!--.*?--></pre>
<p>Regex options: Dot
matches line breaks<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<pre><!--[\s\S]*?--></pre>
<p>Regex options: None<br>
</p><pre>\bTODO\b</pre>
<p>Regex options: Case
insensitive<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h4>Single-step approach</h4>
<pre>\bTODO\b(?=(?:(?!<!--).)*?-->)</pre>
<p>Regex options: Case
insensitive, dot matches line breaks<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<pre>\bTODO\b(?=(?:(?!<!--)[\s\S])*?-->)</pre>
<p>Regex options: Case
insensitive<br>
</p><h3>Discussion</h3>
<h4>Single-step approach</h4>
<pre>\b TODO \b # Match the characters "TODO", as a complete word
(?= # Followed by:
(?: # Group but don't capture:
(?! <!-- ) # Not followed by: "<!--"
. # Match any single character
)*? # Repeat zero or more times, as few as possible (lazy)
--> # Match the characters "-->"
)</pre>
<p>Regex options: Dot
matches line breaks, free-spacing<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h3>Variations</h3>
<pre>(?<=<!--(?:(?!-->).)*?)\bTODO\b(?=(?:(?!<!--).)*?-->)</pre>
<p>Regex options: Case
insensitive, dot matches line breaks<br>
</p><h2>9.11. Change the Delimiter Used in CSV Files</h2>
<h3>Solution</h3>
<pre>(,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")?</pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>( , | \r?\n | ^ ) # Capture the leading field delimiter to backref 1
( # Capture a single field to backref 2:
[^",\r\n]+ # Unquoted field
| # Or:
" (?:[^"]|"")* " # Quoted field (may contain escaped double quotes)
)? # The group is optional because fields may be empty</pre>
<p>Regex options: Free-spacing<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h4>Example web page with JavaScript</h4>
<pre><html>
<head>
<title>Change CSV delimiters from commas to tabs</title>
</head>
<body>
<p>Input:</p>
<textarea id="input" rows="5" cols="75"></textarea>
<p><input type="button" value="Replace" onclick="commasToTabs()"></p>
<p>Output:</p>
<textarea id="output" rows="5" cols="75"></textarea>
<script>
function commasToTabs() {
var input = document.getElementById("input"),
output = document.getElementById("output"),
regex = /(,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")?/g,
result = "",
match;
while (match = regex.exec(input.value)) {
// Check the value of backreference 1
if (match[1] == ",") {
// Add a tab (in place of the matched comma) and backreference
// 2 to the result. If backreference 2 is undefined (because
// the optional, second capturing group did not participate in
// the match), use an empty string instead.
result += "\t" + (match[2] || "");
} else {
// Add the entire match to the result
result += match[0];
}
// If there is an empty match, prevent some browsers from getting
// stuck in an infinite loop
if (match.index == regex.lastIndex) {
regex.lastIndex++;
}
}
output.value = result;
}
</script>
</body>
</html></pre>
<h2>9.12. Extract CSV Fields from a Specific Column</h2>
<h3>Solution</h3>
<pre>(,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")?</pre>
<p>Regex options: None<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>( , | \r?\n | ^ ) # Capture the leading field delimiter to backref 1
( # Capture a single field to backref 2:
[^",\r\n]+ # Unquoted field
| # Or:
" (?:[^"]|"")* " # Quoted field (may contain escaped double quotes)
)? # The group is optional because fields may be empty</pre>
<p>Regex options: Free-spacing<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h4>Example web page with JavaScript</h4>
<pre><html>
<head>
<title>Extract the third column from a CSV string</title>
</head>
<body>
<p>Input:</p>
<textarea id="input" rows="5" cols="75"></textarea>
<p><input type="button" value="Extract Column 3"
onclick="displayCsvColumn(2)"></p>
<p>Output:</p>
<textarea id="output" rows="5" cols="75"></textarea>
<script>
function displayCsvColumn(index) {
var input = document.getElementById("input"),
output = document.getElementById("output"),
columnFields = getCsvColumn(input.value, index);
if (columnFields.length > 0) {
// Show each record on its own line, separated by a line feed (\n)
output.value = columnFields.join("\n");
} else {
output.value = "[No data found to extract]";
}
}
// Return an array of CSV fields at the provided, zero-based index
function getCsvColumn(csv, index) {
var regex = /(,|\r?\n|^)([^",\r\n]+|"(?:[^"]|"")*")?/g,
result = [],
columnIndex = 0,
match;
while (match = regex.exec(csv)) {
// Check the value of backreference 1. If it's a comma,
// increment columnIndex. Otherwise, reset it to zero.
if (match[1] == ",") {
columnIndex++;
} else {
columnIndex = 0;
}
if (columnIndex == index) {
// Add the field (backref 2) at the end of the result array
result.push(match[2]);
}
// If there is an empty match, prevent some browsers from getting
// stuck in an infinite loop
if (match.index == regex.lastIndex) {
regex.lastIndex++;
}
}
return result;
}
</script>
</body>
</html></pre>
<h3>Variations</h3>
<h4>Match a CSV record and capture the field in column 1 to
backreference 1</h4>
<pre>^([^",\r\n]+|"(?:[^"]|"")*")?(?:,(?:[^",\r\n]+|"(?:[^"]|"")*")?)*</pre>
<p>Regex options: ^ and
$ match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h4>Match a CSV record and capture the field in column 2 to
backreference 1</h4>
<pre>^(?:[^",\r\n]+|"(?:[^"]|"")*")?,([^",\r\n]+|"(?:[^"]|"")*")?(?:,(?:[^",\r\n]+|"(?:[^"]|"")*")?)*</pre>
<p>Regex options: ^ and
$ match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h4>Match a CSV record and capture the field in column 3 or higher
to backreference 1</h4>
<pre>^(?:[^",\r\n]+|"(?:[^"]|"")*")?(?:,(?:[^",\r\n]+|"(?:[^"]|"")*")?){1},([^",\r\n]+|"(?:[^"]|"")*")?(?:,(?:[^",\r\n]+|"(?:[^"]|"")*")?)*</pre>
<p>Regex options: ^ and
$ match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h4>Replacement string</h4>
<pre>$1</pre>
<pre>\1</pre>
<h2>9.13. Match INI Section Headers</h2>
<h3>Solution</h3>
<pre>^\[[^\]\r\n]+]</pre>
<p>Regex options: ^ and $
match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h3>Variations</h3>
<pre>^\[Section1]</pre>
<p>Regex options: ^ and $
match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<h2>9.14. Match INI Section Blocks</h2>
<h3>Solution</h3>
<pre>^\[[^\]\r\n]+](?:\r?\n(?:[^[\r\n].*)?)*</pre>
<p>Regex options: ^ and $
match at line breaks (“dot matches line breaks” must not be
set)<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>^ \[ [^\]\r\n]+ ] # Match a section header
(?: # Followed by the rest of the section:
\r?\n # Match a line break character sequence
(?: # After each line starts, match:
[^[\r\n] # Any character except "[" or a line break character
.* # Match the rest of the line
)? # The group is optional to allow matching empty lines
)* # Continue until the end of the section</pre>
<p>Regex options: ^ and $
match at line breaks, free-spacing (“dot matches line breaks” must not
be set)<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
<h3>Discussion</h3>
<pre>[Section1]
Item1=Value1
Item2=[Value2]
; [SectionA]
; The SectionA header has been commented out
ItemA=ValueA ; ItemA is not commented out, and is part of Section1
[Section2]
Item3=Value3
Item4 = Value4</pre>
<h2>9.15. Match INI Name-Value Pairs</h2>
<h3>Solution</h3>
<pre>^([^=;\r\n]+)=([^;\r\n]*)</pre>
<p>Regex options: ^ and $
match at line breaks<br>
Regex flavors: .NET,
Java, JavaScript, PCRE, Perl, Python, Ruby</p>
<pre>^ # Start of a line
( [^=;\r\n]+ ) # Capture the name to backreference 1
= # Name-value delimiter
( [^;\r\n]* ) # Capture the value to backreference 2</pre>
<p>Regex options: ^ and $
match at line breaks, free-spacing<br>
Regex flavors: .NET,
Java, XRegExp, PCRE, Perl, Python, Ruby</p>
</body></html>