4

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?

0

2 Answers 2

5

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.

4

The problem you are having is stemming from the fact that -p implies -n, which evaluates the program for each line of the file.

Your problem can be solved by only attempting the substitution on the first line of the file.

perl -pe's{^(?!syntax:)}{syntax: glob\n\n} if $. == 1' .hgignore

Alternatively, you could tell Perl the whole file is one line with -0777 or the newer -g.

perl -0777pe's{^(?!syntax:)}{syntax: glob\n\n}' .hgignore

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.