Search code examples
stringperlmultiline

`perl -pe` match only start of file?


I'm trying

perl -pe 's;\A(?!syntax:);syntax: glob\n\n;' .hgignore

On a file with these contents:

dist
node_modules
.vscode

The output I expect is:

syntax: glob

dist
node_modules
.vscode

With the caveat that I can run it repeatedly and it won't keep pre-pending.

I use \A(?!syntax:) to anchor the regex to the start of the file and then (?! to say "not followed by". Looks like \A is matching the start of the line, not start of file.

How can I match only the very start of the file?


Solution

  • With the -p switch the file is read line by line, to start with. So the code never sees the whole file, only one line at a time.

    To "slurp" the whole file into $_ do perl -0777 -pe'...' file. That -0777 unsets the input record separator, so the "line" read by -p is really the whole file. See it in perlrun

    Then the regex will run on the multiline string with the whole file.

    With a multiline string one often needs the /m modifier, so that ^ and $ match beginning and end of lines inside the string, while we have \A to match the beginning of the whole string. One also often needs the /s modifier, so that . matches a newline as well.

    However, it seems that for your purpose those aren't needed. Then, without the /m modifier the ^ anchor matches the beginning of the string, just like \A. But I do find \A still better as it expresses the intent clearly.