3
\$\begingroup\$

I sometimes save nice fortune outputs to my Evernote. The data looks like this:

/ Abou Ben Adhem (may his tribe increase!)                    \
| Awoke one night from a deep dream of peace,                 |
| And saw, within the moonlight in his room,                  |
| Making it rich, and like a lily in bloom,                   |
| An angel writing in a book of gold.                         |
| Exceeding peace had made Ben Adhem bold,                    |
| And to the presence in the room he said,                    |
| "What writest thou?"  The vision raised its head,           |
| And with a look made of all sweet accord,                   |
| Answered, "The names of those who love the Lord."           |
| "And is mine one?" said Abou. "Nay not so,"                 |
| Replied the angel.  Abou spoke more low,                    |
| But cheerly still; and said, "I pray thee then,             |
| Write me as one that loves his fellow-men."                 |
| The angel wrote, and vanished.  The next night              |
| It came again with a great wakening light,                  |
| And showed the names whom love of God had blessed,          |
| And lo!  Ben Adhem's name led all the rest.                 |
\                 -- James Henry Leigh Hunt, "Abou Ben Adhem"

I am using the following regex:

$ cat abcd | sed -r 's/^[/|\\]\s?([-A-Za-z ()!,?".;'"'"']*)[/|\\]?/\1/'
Abou Ben Adhem (may his tribe increase!)                    
Awoke one night from a deep dream of peace,  
...

How do I improve it?

\$\endgroup\$
  • \$\begingroup\$ Do you just want to remove |, / and \ from the beginning and end of every line? I am asking this because I am not sure why your regex is so complicated. \$\endgroup\$ – Arkadiusz Drabczyk Jul 27 '15 at 9:24
  • \$\begingroup\$ @ArkadiuszDrabczyk Yes. I simply can't figure out a simpler way. \$\endgroup\$ – ps95 Jul 27 '15 at 9:25
  • \$\begingroup\$ I have rolled back the last edit. Please see what you may and may not do after receiving answers. \$\endgroup\$ – Heslacher Jul 27 '15 at 12:18
5
\$\begingroup\$

Your regex looks complicated. What's more, it doesn't work:

$ cat fortune | sed -r 's/^[/|\\]\s?([-A-Za-z ()!,?".;'$a']*)[/|\\]?/\1/'
Abou Ben Adhem (may his tribe increase!)
Awoke one night from a deep dream of peace,
And saw, within the moonlight in his room,
Making it rich, and like a lily in bloom,
An angel writing in a book of gold.
Exceeding peace had made Ben Adhem bold,
And to the presence in the room he said,
"What writest thou?"  The vision raised its head,
And with a look made of all sweet accord,
Answered, "The names of those who love the Lord."
"And is mine one?" said Abou. "Nay not so,"
Replied the angel.  Abou spoke more low,
But cheerly still; and said, "I pray thee then,
Write me as one that loves his fellow-men."
The angel wrote, and vanished.  The next night
It came again with a great wakening light,
And showed the names whom love of God had blessed,
And lo!  Ben Adhem's name led all the rest.                 |
                -- James Henry Leigh Hunt, "Abou Ben Adhem"

See this stray | in the second line from the bottom? Honestly, I didn't analyze why your regex doesn't work because, as I said, it looks horribly complicated. But, first of all, cat is not necessary here because most of sed implementations - GNU, busybox, BSD can operate on a file directly and some of them even take i parameter which makes sed modify a file in place. That being said, here's how I would do it:

$ sed -r 's,^(/|\||\\) ,,g' fortune | sed -r 's,(\\|\|)$,,g'

I tested it with GNU sed 4.2.1 and with busybox version of sed on OpenWRT. The only thing that I don't like about it is usage of -r. There may be some basic sed implementations that don't implement extended regular expressions but they should be very rare.

EDIT: No chaining with perl:

$ perl -pe 's,^(/|\||\\) (.+?)(\\|\|)?$,\2,' fortune
\$\endgroup\$
  • \$\begingroup\$ I will agree it's complicated, but it definately works. I edited the question. And yours only removes the ending tag. That is trivial. I need a better way to capture the middle string. \$\endgroup\$ – ps95 Jul 27 '15 at 9:37
  • \$\begingroup\$ No, I use | to chain two sed commands. The first one removes redundant characters at the beginning: s,^(/|\||\\) ,,g. What version of sed do you use? I use fortune as the file name. \$\endgroup\$ – Arkadiusz Drabczyk Jul 27 '15 at 9:39
  • \$\begingroup\$ Thanks! I incorporated your suggestion and indeed using two sed is much simpler. However, I am wondering if it's possible to do it with just one? And sure sed -r <file> is better, but I find cat <file> | sed easier to read. \$\endgroup\$ – ps95 Jul 27 '15 at 9:48
  • \$\begingroup\$ @prakharsingh95: in the old days, there used be something called useless use of cat on Usenet. To answer your question - I wouldn't go with sed if I wanted to avoid chaining because sed does not support non-greedy matches: stackoverflow.com/questions/1103149/…. I would use Perl. I will update my answer in a second. \$\endgroup\$ – Arkadiusz Drabczyk Jul 27 '15 at 10:34
  • \$\begingroup\$ Thanks. I generally use Regex in Java or online, and I never thought sed wouldn't support non-greedy. Accepting this answer. \$\endgroup\$ – ps95 Jul 27 '15 at 10:56

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

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