# Perl String Matching Problem

**URL:** https://boards.straightdope.com/t/perl-string-matching-problem/313123
**Category:** Factual Questions
**Created:** [July 19, 2005, 11:39am UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123 "2005-07-19T11:39:31Z")
**Posts on this page:** 10
**Page:** 1

<div class="post-metadata">

### Author: ![bluecanary](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/bluecanary/32/3614_2.png) [@bluecanary](https://boards.straightdope.com/u/bluecanary)
#### Post date: [July 19, 2005, 11:39am UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/1 "2005-07-19T11:39:31Z")

</div>

I am trying to write a Perl script, a part of which is to match strings from one file with another file, and print out further information from the appropriate line of the file if there is a match. Mostly this is working fine, other than in cases where the text that needs to be matched contains parentheses or brackets.

In these cases, the a match does not occur even if the strings are exactly the same. I have confirmed that this is the case for the troublesome examples. I have a good idea that it is something to do with parentheses being ‘metacharacters’, but attempting to escape the brackets by putting backslashes before them in both files (at an earlier stage in the script) produced the following error in the matching routine:

Unmatched ) in regex; marked by \<-- HERE in m/^) \<-- HERE / at datafile\_parser.pl line 139, \<DATA\_TOMATCH\_IN\> line 219

What am I doing wrong?

---

<div class="post-metadata">

### Author: ![Mops](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/mops/32/16494_2.png) [@Mops](https://boards.straightdope.com/u/Mops)
#### Post date: [July 19, 2005, 12:20pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/2 "2005-07-19T12:20:56Z")

</div>

My guess from the error message is that you interpolate the text to be matched into the regex, right?

In that case you need to escape your special characters twice, e.g. if the text to be matched is **(wordinbrackets)**, the text in the first file must be **\(wordinbrackets\)**, which after the variable interpolation becomes **(wordinbrackets)**.

---

<div class="post-metadata">

### Author: ![Nature\_s\_Call](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/nature_s_call/32/19006_2.png) [@Nature\_s\_Call](https://boards.straightdope.com/u/Nature_s_Call)
#### Post date: [July 19, 2005, 12:25pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/3 "2005-07-19T12:25:30Z")

</div>

> [@bluecanary](#):
>
> I have a good idea that it is something to do with parentheses being ‘metacharacters’, but attempting to escape the brackets by putting backslashes before them **in both files** (at an earlier stage in the script)

Unless I’ve misread your description, you attempted to fix the problem by putting the backslash in the input file. The place for the backslash is in the regular expression.

> [@](#):
>
> Unmatched ) in regex; marked by ← HERE in m/^) ← HERE / at datafile\_parser.pl line 139, \<DATA\_TOMATCH\_IN\> line 219

Based on this snippit from the error message, change **m/^)** in the regex in your script to **m/^)** which reads “Match on a close paren at the beginning of a line.”

Can you post the full regular expression in question, along with samples of the text it is supposed to match?

Also, what version of Perl are you running?

---

<div class="post-metadata">

### Author: ![bluecanary](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/bluecanary/32/3614_2.png) [@bluecanary](https://boards.straightdope.com/u/bluecanary)
#### Post date: [July 19, 2005, 12:27pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/4 "2005-07-19T12:27:22Z")

</div>

No, that doesn’t do it. Three, two, or one backslash before each bracket it doesn’t make any difference to the error message that appears.

The text is put into a temporary file which I then read back in to an array to carry out the matching in the second phase of the script. There are two parallel files at this point, then I use a nested foreach loop to carry out the matching. It works fine for everything but the strings with brackets in them.

---

<div class="post-metadata">

### Author: ![Mops](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/mops/32/16494_2.png) [@Mops](https://boards.straightdope.com/u/Mops)
#### Post date: [July 19, 2005, 12:28pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/5 "2005-07-19T12:28:32Z")

</div>

Or, in actual code,

```auto

if ($secondstring =~ m/^\(wordinbrackets\)/) {
   ...
}

```

is equivalent to

```auto

$firststring = '\\\(wordinbrackets\\\)';
if ($secondstring =~ m/^$firststring/) {
   ...
}

```

The reason being that the backslash is also a special character that needs to be escaped.

---

<div class="post-metadata">

### Author: ![bluecanary](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/bluecanary/32/3614_2.png) [@bluecanary](https://boards.straightdope.com/u/bluecanary)
#### Post date: [July 19, 2005, 12:30pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/6 "2005-07-19T12:30:49Z")

</div>

That above post was a response to **tschild**.

I wrote the backslashes into the temporary file. The closed parenth was not at the beginning of the line in the problematic string. The strings are at the beginning of the line and it’s supposed to match the whole thing until the tab is reached–including the brackets.

This is the string that is causing the problem (I’ve edited the actual text but the structure’s exactly the same:  
string to be matched (text in brackets) 3 Number 41

---

<div class="post-metadata">

### Author: ![bluecanary](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/bluecanary/32/3614_2.png) [@bluecanary](https://boards.straightdope.com/u/bluecanary)
#### Post date: [July 19, 2005, 12:34pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/7 "2005-07-19T12:34:51Z")

</div>

if ($full\_in\_line =~ m/^$the\_example\_name/)  
{  
print DEBUG\_OUT $the\_example\_name;  
print DEBUG\_OUT "  
";  
$match\_found\_in\_iteration = 1;  
}

where $the\_example\_name is the string in the other temp file that is a list of strings, one per line, for which I need to pull out other data from the big file (the one which $full\_in\_line is an array element from).

---

<div class="post-metadata">

### Author: ![Mops](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/mops/32/16494_2.png) [@Mops](https://boards.straightdope.com/u/Mops)
#### Post date: [July 19, 2005, 2:49pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/8 "2005-07-19T14:49:08Z")

</div>

Perhaps you could print out the content of $the\_example\_name, in a line before the regex, to check if it does in fact contain the string that you expect it to contain?

A somewhat inelegant way to get around the ‘special characters in regexes’ problem would be to use a string comparison:

```auto

if (substr($full_in_line, 0, length($the_example_name)) eq $the_example_name)
...

```

---

<div class="post-metadata">

### Author: ![friedo](https://avatars.discourse-cdn.com/v4/letter/f/8edcca/32.png) [@friedo](https://boards.straightdope.com/u/friedo)
#### Post date: [July 19, 2005, 2:56pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/9 "2005-07-19T14:56:30Z")

</div>

To prevent interpolation of metacharacters in a string, use the \Q (quote) assertion:

m/\Q$some\_string\E/

---

<div class="post-metadata">

### Author: ![bluecanary](https://sea3.discourse-cdn.com/straightdope/user_avatar/boards.straightdope.com/bluecanary/32/3614_2.png) [@bluecanary](https://boards.straightdope.com/u/bluecanary)
#### Post date: [July 19, 2005, 3:22pm UTC](https://boards.straightdope.com/t/perl-string-matching-problem/313123/10 "2005-07-19T15:22:15Z")

</div>

Thanks **friedo** , that seems to have done the trick (without any escape characters inserted into the temp files). The troublesome entry is now in the report file with the others, and I didn’t have to fudge it by substituting the brackets out.
