Rebecca
Rebecca

Reputation: 23

Inserting headers into multiple files

I found some command line with Perl that inserts headers into my files without going through the tedious process of inserting them one by one. Can someone walk me through the Perl aspect of this command line? I'm new to this and can't seem to find the right explanations for what I wrote.

cat header.txt | perl -0 -i -pe 'BEGIN{$h = <STDIN>}; print $h' 1*

Upvotes: 2

Views: 803

Answers (2)

djeikyb
djeikyb

Reputation: 4588

Here's something similar, with an explanation. The program in the question doesn't run on my mac.

I needed to add the #nullable disable directive to the top of all my csharp files as part of migrating to nullable reference types.

perl -w -i -p -0777 -e 's/^/#nullable disable\n\n/' $(find . -iname '*.cs')
  • -w enable warnings
  • -i edit files in place
  • -p read each file block by block, printing each block after applying a perl expression. the default block size is one line
  • -0777 changes the default block size to the entire file
  • -e the perl expression to execute

The final argument uses shell command substitution to create a list of files. It passes that list of file paths to the perl command. The find command searches for files that end in .cs.

The perl program is a single substitution command. It matches the very beginning of the block and replaces (prepends, really) with "#nullable disable" and a couple new-lines.

Upvotes: 1

Android Newbie
Android Newbie

Reputation: 711

-e rather than provide a script in a xxxx.pl file, provide it on the command line

-p makes it iterate over filename arguments somewhat like sed but also prints the contents of $_ at the end of the script.

the two above are combined in -pe

-i indicate you want to edit the file in place and write the output to the same file. In practice, Perl renames the input file and reads from this renamed version while writing to a new file with the original name

-0 redefines the end of record character (\n by default) so that you can read the entire input file as a single line

1* is the command line argument to your script, so I guess you are modifying any file with a name that starts with 1 (you could have used *.c, or whatever depending on the type of files you are trying to modify)

print $h prints the variable $h that is the "main" of your script. if it was initialized with the content of the header file (the intent of this one-liner) then it will print the header file

BEGIN{ some code here } this is stuff you execute before the script starts. this is where I'm stumped. this doesn't seem like valid perl code

so basically:

  • this will supposedly slurp the entire header file (because of -0) in the BEGIN block and store it in the variable $h
  • iterate over all the files specified by the wildcards at the end of the command line
  • for each file: print the header (print $h) then print hte file itself (because of -pe)

so it's equivalent to spelling the script out:

$h = gets content of the entire header file
while (<>){ #loop implied by -pe, iterates over all the 1* files
    # the main contents of the "-e" script are inserted below as part of executing -pe
    print h$; #print the header we saved 
    print $_; # implied by -pe, and since we are using -0, this prints the entire content in one shot
    # end of the "-e" script. again it was a single print $h statement, the second print is implied by -pe
} 

It's a bit hard to explain, take a look at the perlrun documentation for details (run man perlrun).

This is not 100% complete explanation because I don;t think the BEGIN block is right. I tried it on my ubuntu machine and it complained about its syntax too

Upvotes: 2

Related Questions