1

I want to match the beginning of lines where the line contains something.

Command in Perl/Sed

's/^.?/\section{}/g'

but the problem here is that it replaces also the first character of sentences.

How can you add to the beginning of lines something for non-empty lines?

  • 2
    I think what you want is not clear. Do you want to add something to the beginning of some lines ? – Esref Jun 15 '15 at 10:55
  • Show sample input and your desired output for that sample input. – Cyrus Jun 15 '15 at 10:57
5
sed '/./s/^/\\section{}/'

Would prepend \section{} to every line that contain at least one valid character.

sed '/^$/!s/^/\\section{}/'

Would prepend \section{} to every non-empty line (that is lines that contain at least one byte).

sed 's/./\\section{}&/'

Would insert \section{} before the first valid character in every line (that has such a valid character). (& is replaced by the matched portion).

Those distinctions between byte and character can be meaningfull if you're in a multi-byte-per-character locale (like UTF-8 which tends to be the norm nowadays) but dealing with text encoded in an extended single-byte character set.

For instance:

$ locale charmap
UTF-8
$ echo Москва | iconv -t iso-8859-5 | sed 's/./\\section{}&/' | iconv -f iso-8859-5
Москва

(when encoded in iso-8859-5, none of the resuling byte values for Москва form a valid character in UTF-8, so /./ doesn't match anything).

Since in your case, encoding would not be a concern since the text you're inserted is ASCII anyway, you can fix the locale to C to avoid surprises:

$ echo Москва | iconv -t iso-8859-5 | LC_ALL=C sed 's/./\\section{}&/' | iconv -f iso-8859-5
\section{}Москва
  • What can happen if you do not do this LC_ALL=C? I have seen sometimes symbols like <CR> ... in my text-editors in working between terminal and text-editor. Can this help for stopping this from happening? – Léo Léopold Hertz 준영 Jun 15 '15 at 11:29
  • @Masi, see the edit for an example of a problem addressed by LC_ALL=C. CR are another kind of problem not related with locales. CR is a character in all locales. It is not the line delimiter character on Unix, so would be part of the content of the line and then matched by .. It is generally considered a vertical spacing character. You could replace your /./ with /[^[:space:]]/ to match on lines that contain at least one non-spacing character. – Stéphane Chazelas Jun 15 '15 at 11:45
  • How can you confirm this locale setting LC_ALL=C, for instance in Perl? – Léo Léopold Hertz 준영 Jun 19 '15 at 15:59
  • 1
    @Masi, perl ignores the locale unless you use things like -CL or -Mopen=locale or -Mlocale... or the equivalent use statements. See perldoc perllocale for details. – Stéphane Chazelas Jun 19 '15 at 16:04
  • So no locale need to be set then with strict and warnings in Perl. I am converting my one-liners to Perl with strict and warning packages. Is this a good solution to avoid the problem with locale? – Léo Léopold Hertz 준영 Jun 19 '15 at 16:08
2

You could do it in two statements with sed : the first one to ensure no empty lines are matched, the second to append at the beginning :

sed '/^$/n;s/^/\\section{}/'

Or you could do it in one statement by capturing what you match and adding it to your replacement :

sed 's/^\(.\)/\\section{}\1/'

Here, the parentheses \( and \) define a capturing group referenced by the \1 in the replacement part of the statement.

Also note that, in order to make sure the line isn't empty, you need to remove the interrogation mark ? after the dot .. ? means "0 or 1", so the empty line would match the 0-length.

  • I like the first one which I also think is more efficient, since no regex there. – Léo Léopold Hertz 준영 Jun 15 '15 at 11:03
0

Use a zero-width positive look-ahead assertion:

perl -pe 's/^(?=.)/\section{}/'

perlre says:

(?=pattern) A zero-width positive look-ahead assertion. For example, /\w+(?=\t)/ matches a word followed by a tab, without including the tab in $&

Another solution:

perl -lpe 's/^/\section{}/ if length'

You should chomp \n at the end of a line before length checking.

The -l option do it for you.

-l[octnum] enables automatic line-ending processing. It has two separate effects. First, it automatically chomps $/ (the input record separator) when used with -n or -p. Second, it assigns $\ (the output record separator) to have the value of octnum so that any print statements will have that separator added back on. If octnum is omitted, sets $\ to the current value of $/

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.