Help me understand this Perl statement with <<'ESQ' - perl

substr($obj_strptime,index($strptime,"sub")+6,0) = <<'ESQ';
shift; # package
....
....
ESQ
What is this ESQ and what is it doing here? Please help me understand these statements.

It marks the end of a here-doc section.
EOF is more traditional than ESQ though.

This construct is known as a here-doc (because you're getting standard input from a document here rather than an external document on the file system somewhere).
It basically reads everything from the next line up to but excluding an end marker line, and uses that as standard input to the program or command that you're running. The end marker line is controlled by the text following the <<.
As an example, in bash (which I'm more familiar with than Perl), the command:
cat <<EOF
hello
goodbye
EOF
will run cat and then send two lines to its standard input (the hello and goodbye lines). Perl also has this feature though the syntax is slightly different (as you would expect, given it's a different language). Still, it's close enough for the explanation to still hold.
Wikipedia has an entry for this which you probably would have found had you known it was called a here-doc, but otherwise it would be rather hard to figure it out.
You can basically use any suitable marker. For example, if one of your input lines was EOF, you couldn't really use that as a marker since the standard input would be terminated prematurely:
cat <<EOF
This section contains the line ...
EOF
but then has more stuff
and this line following is the real ...
EOF
In that case, you could use DONE (or anything else that doesn't appear in the text on its own line).
There are other options such as using quotes around the marker (so the indentation can look better) and the use of single or double quotes to control variable substitution.
If you go to the perlop page and search for <<EOF, it will hopefully all become clear.

Related

Substitution/Replacement problem with a data file Perl, Sublime

My file is x in the format \D{5}\d\d/ D{5}\d or |D{5}dd
example:
aahed9aalii5aargh9abaca9abaci9aback13
The /d may be 1 or 2 digits no spaces or breaks in the entire document.
The goal is to create a .csv file dividing the \D{5} from \d{1} or \d{2}
Tried sublime text,perl,textedit or pages
In Sublime I understand how to find the (\D{5} group) but not how to replace that with (\D{5}),)
I found the s(dog/cat)substitution example but could not get that to translate in perl or sublime.
Found the perl command line idea
(perl -pi.bak -e 's\/D{5}/D{5}\,/g' $filename) may not be exact
But could not decipher all the errors
The reason I chose regex for this is the only commonality to each value is the length of the word is the same throughout the document. There are no tabs, no parens, no spaces, no fixed length fields nothing to get my hooks in.
The question:
How do I retain the original values in the replace/substitution function?
I realize what this board has to deal with in regard to duplicate
questions. Do you realize on my side how difficult it is to search through all the previous questions when I am not sure what I am looking for?
I am not looking for someone to give me a fish, looking for someone to teach me how to fish.
If REGEX is not the answer maybe I am missing something any guidance would be appreciated.
Thanks
The $1, $2, etc variables may be used to refer back to "captures" (parenthesized parts) within the most recent regexp.
echo aahed9aalii5aargh9abaca9abaci9aback13 | perl -pe 's/(\D{5})(\d*)/$1=$2,/g'
Outputs:
aahed=9,aalii=5,aargh=9,abaca=9,abaci=9,aback=13,

How to match \n\n using perl one liner?

My Sample file:
As I Come Into Your Presence
Key: F
1 As I come into Your presence
Past the gates of praise
Into Your sanctuary
Till we are standing face to face
And look upon Your countenance
I see the fullness of Your glory
And I can only bow down and say
Chorus:
Your awesome in this place
Mighty God
You are awesome in this place
Abba Father
You are worthy of all praise
To You our lives we raise
You are awesome in this place
Mighty God
<--- Empty line here
<--- Empty line here
I wrote this perl one-liner to get <i></i> tags around the entire chorus block:
perl -p0e "s#Chorus:(.*?)\n\n#<i>Chorus:$1</i>#gsm" file
The result:
As I Come Into Your Presence
Key: F
1 As I come into Your presence
Past the gates of praise
Into Your sanctuary
Till we are standing face to face
And look upon Your countenance
I see the fullness of Your glory
And I can only bow down and say
<i>Chorus:</i>%
I can't get the desired result where the </i> tag would be printed after the entire chorus after the Mighty God.
Where is the error? How can I achieve this?
Your solution would work if you just put it in single quotes instead of double quotes. You should pretty much always use single quotes for one-liners from the shell, no matter what language/interpreter you're running, to keep shell interpolation from messing things up.
In your code:
perl -p0e "s#Chorus:(.*?)\n\n#<i>Chorus:$1</i>#gsm" file
The $1 is being expanded by the shell before it ever gets to Perl, so Perl sees this:
perl -p0e "s#Chorus:(.*?)\n\n#<i>Chorus:</i>#gsm" file
and happily deletes your chorus. If you use single quotes instead:
perl -p0e 's#Chorus:(.*?)\n\n#<i>Chorus:$1</i>#gsm' file
it will work as intended.
Note, however, that the -0 means any NUL characters that creep into the input will still cause Perl to split it into multiple records at that point. A more correct solution would be to use -0777 instead, which tells Perl that no value should split the input; it is treated as a single record no matter what data it contains.
perl -p0777e 's#Chorus:(.*?)\n\n#<i>Chorus:$1</i>#gsm' file
escape the $
perl -p0777e "s#Chorus:(.*?)\n\n#<i>Chorus:\$1</i>#gsm" file.
also as #Kenney mention in the comment:
Use single quotes on the commandline to wrap perl expressions otherwise the shell expansion will kick in.

How to understand this perl multi-line writing command

I am trying to understand the perl commands below:
$my = << EOU;
This is an example.
Example too.
EOU
What is the name of this way? Could somebody can explain more about this "multi-line writing" command?
Essentially the syntax is allowing you to put anything unique as a marker so that it won't conflict with your contents. You can do this:
$my = <<ABCDEFG;
This is an example.
Example too.
BLAH
ABCDEFG
Everything between "This.." and "BLAH" will be assigned to the variable. Note that you shouldn't have a space after the << symbols otherwise you will get a syntax error. It helps avoid adding CR characters, or append (.) everywhere, and useful when passing data into another application (eg. ftp session). Here Documents is the correct term for this.
Everything between <<EOU and EOU is a multi-line, non-escapable, string. It's nothing fancy, think of them as start and end quote marks with nothing inside requiring escapes to be literally what you typed...

What is print <<EOF; and how is it working? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Help me understand this Perl statement with <<'ESQ'
What is the statement in https://stackoverflow.com/questions/4151279/perl-print-eof doing exactly? I came across the previous post but didn't understand what he is trying to explain. What is that PETE? Can anyone explain every line? How is the code is working?
print <<EOF;
This is
a multiline
string
EOF
print <<PETE;
This is
a multiline
string
PETE
What is the difference and similarity between these two? In place of PETE I have used many other words like DOG and it works the same every time.
This is called a here-doc. It basically grabs everything from the next line up until an end marker line and presents that as standard input to the program you're running. The end marker line is controlled by the text following the <<.
As an example, in bash (which I'm more familiar with than Perl), the command:
cat <<EOF
hello
goodbye
EOF
will run cat and then send two lines to its standard input (the hello and goodbye lines). Perl also has this feature though the syntax is slightly different (as you would expect, given it's a different language). Still, it's close enough for the explanation to still hold.
Wikipedia has an entry for this which you probably would have found had you known it was called a here-doc, but otherwise it would be rather hard to figure it out.
In your particular cases, there is no difference between using EOF and PETE, there's a relationship between the heredoc marker (the bit following <<) and the end of standard input.
For example, if one of your input lines was EOF, you couldn't really use that as a marker since the standard input would be terminated prematurely:
cat <<EOF
This section contains the line ...
EOF
but then has more stuff
and this line following is the real ...
EOF
In that case, you could use PETE (or anything else that doesn't appear in the text on its own line).
There are other options such as using quotes around the marker (so the indentation can look better) and the use of single or double quotes to control variable substitution.
If you go to the perlop page and search for <<EOF, it will hopefully all become clear.
See Quote and Quote-like Operators (it's pretty well explained).

How to search and replace empty line after specific token?

I want to delete newlines after lines containing a keyword e.g. like modifiers private:,public: or protected: to fulfill our coding standard. I need a command line tool (Linux) for this, so please no Notepad++, Emacs, VS, or Vim solutions, if they require user interaction. So in other words I want to do a:
sed -i 's/private:\s*\n\s*\n/private:\n/g'
I've seen this question but was unable to extend it to my needs.
If I understand correctly, you want to remove empty lines which follow a line containing private:, public:, or protected:.
sed ':loop;/private:\|public:\|protected:/{n;/^$/d;Tloop}' inputfile
Explanation:
:loop create a label
/private:\|public:\|protected:/ will search for lines containing the pattern.
n;/^$/d will load the next line (n), check whether it is an empty line (/^$/), and if it is, delete the line (d).
Tloop branch to label loop if there was no match (line was not empty)
I am no sed guru, there might be more elegant ways to do this. There might also be more elegant ways to do this in awk, perl, python, whatever.
perl -0777 -pi -e 's/([ \t\r]*)(private|protected|public):[ \t\r]*\n[ \t\r]*\n/$1$2:\n/g' file
should do the trick, while also take trailing and leading whitespace into account, which I didn't specified in the question as this is not a must requirement.