Server Fault is a question and answer site for system and network administrators. Join them; it only takes a minute:

Sign up
Here's how it works:
  1. Anybody can ask a question
  2. Anybody can answer
  3. The best answers are voted up and rise to the top

I'm building a script which filters out all our translatables from our template system. the problem i'm facing is the occasion where 2 translatables are on one line.

These are 2 example lines from a template file which both hold one or more translatables

<img src="/captcha/generate.jpg" alt="[#Captcha#]" />
<span>[#Velden met een * zijn verplicht in te vullen#]</span> <button type="submit" name="frm_submit" class="right">[#Verzend#]

And when i set loose the following regexp

egrep "\[#(.*)#\]" . -Rohis

I get this output

[#Velden met een * zijn verplicht in te vullen#]</span> <button type="submit" name="frm_submit" class="right">[#Verzend#]

While the desired output is

[#Velden met een * zijn verplicht in te vullen#]
share|improve this question
up vote 1 down vote accepted

Agree with Kyle. However, in this case, you could do this: egrep "\[#([^]])*)#\]" . -Rohis and get what you're looking for.

The [^]]* matches non-] characters, so it'll stop at the first ] it hits.

share|improve this answer

Trying to parse HTML with regular expressions leads to pain, just don't do it. Jeff wrote about it in Parsing Html The Cthulhu Way. "But I only want to __", doesn't matter, seriously, don't do it. Take a little time and learn something designed to parse html.

I personally would recommend a Perl Module for this (such as HTML::TreeBuilder), but what languages do you know? Other options are: tidy+ xmlstarlet xmlgawk xpath xml2.

If you just want the "rendered" html in text, you can use something like links: links -dump

share|improve this answer
I'm not trying to parse HTML, i'm trying to compile a list of all translation strings used in our framework, wether they are in a html, tpl, txt, csv or php file doesn't mater, nor does the context. – ChrisR Feb 4 '10 at 14:46
Ah, well the negated character class is the general way to get non-greedy like operations as others stated. – Kyle Brandt Feb 4 '10 at 15:03

Seconded Kyle comment.

Anyway, if the pattern is sufficiently uniform, you can achieve what you want my matching anything but the closing character, i.e.

egrep "\[#([^]]*)#\]" ...

This pattern will not work if you have closing ] inside the text, e.g. [#xyz]#] will not match.

share|improve this answer

Use Perl, which lets you do non-greedy matches. For your case where you watch multiple matches, do it like with the /g modifier. We add the -l switch because we have to handle linefeeds ourselves:

perl -lne'while(/\[#(.*?)#\]/g) {print $&}' filename
share|improve this answer

Your Answer


By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.