Idiomatic way to long multistring constants (or vars) in Lisp code - lisp

What is idiomatic way for inserting long multistrings vars or constants in Common Lisp code?
Is there something like HEREDOC in unix shell or some other languages, to eliminate indenting spaces inside string literals?
For example:
(defconstant +help-message+
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here")
; ^^^^^^^^^^^ this spaces will appear - not good
And writing this way kinda ugly:
(defconstant +help-message+
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here")
How we should write it. If there any way, when you don't need to escape quotes it'll be even better.

I don't know about idiomatic, but format can do this for you. (naturally. format can do anything.)
See Hyperspec section 22.3.9.3, Tilde newline. Undecorated, it removes both newline and subsequent whitespace. If you want to preserve the newline, use the # modifier:
(defconstant +help-message+
(format nil "Blah blah blah blah blah~#
blah blah blah blah blah~#
some more more text here"))
CL-USER> +help-message+
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here"

There is no such thing.
Indentation is usually:
(defconstant +help-message+
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here")
Maybe use a reader macro or read-time eval. Sketch:
(defun remove-3-chars (string)
(with-output-to-string (o)
(with-input-from-string (s string)
(write-line (read-line s nil nil) o)
(loop for line = (read-line s nil nil)
while line
do (write-line (subseq line 3) o)))))
(defconstant +help-message+
#.(remove-3-chars
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here"))
CL-USER 18 > +help-message+
"Blah blah blah blah blah
blah blah blah blah blah
some more more text here
"
Would need more polishing... You could use 'string-trim' or similar.

I sometimes use this form:
(concatenate 'string "Blah blah blah"
"Blah blah blah"
"Blah blah blah"
"Blah blah blah")

Related

Using sed, how can I append a string to lines that contain a pattern and don't already have the string appended?

Eq.
I have file with the following contents
ERR001 just some random text
ERR002 blah blah blah
ERR001 again some text //IGNORE
ERR001 blah blahblah blah blah
ERR002 abc def ghi
I to write a sed command that append //IGNORE to all line that have ERR001 but do not already have //IGNORE appended. So the sed command should give the below output for the above file
ERR001 just some random text //IGNORE
ERR002 blah blah blah
ERR001 again some text //IGNORE
ERR001 blah blahblah blah blah //IGNORE
ERR002 abc def ghi
sed solution:
sed '/\/\/IGNORE$/! s/^ERR001 .*/& \/\/IGNORE/' inputfile
/\/\/IGNORE$/! - negated matching, ensures that line is not ended with //IGNORE (! - negation sign)
s/^ERR001 .*/& \/\/IGNORE/ - substitute a line that started with ERR001
The output:
ERR001 just some random text //IGNORE
ERR002 blah blah blah
ERR001 again some text //IGNORE
ERR001 blah blahblah blah blah //IGNORE
ERR002 abc def ghi

How do I comment the first line of a pattern block where all lines should be commented?

I have a pattern block like this:
<domain hotmail.com>
blah
blah
blah
</domain>
I want the final output to look like this:
#<domain hotmail.com>
#blah
#blah
#blah
#</domain>
Using this command I can get all but the 1st line which is the match to start the pattern:
sed -e "/\(^<domain hotmail.com>\)/{:a;n;s/^/#/;/<\/domain>/!ba;}" file
Which give me this:
<domain hotmail.com>
#blah
#blah
#blah
#</domain>
The number of lines between and will vary. The above code works for the variance but not on the first line. How can I get the first line commented?
Thanks,
John
sed '/<domain hotmail\.com>/,/<\/domain>/ s/^/#/'
Testing:
sed '/<domain hotmail\.com>/,/<\/domain>/ s/^/#/' <<END
foo
<domail yahoo.com>
blah
blah
</domain>
qux
<domain hotmail.com>
blah
blah
blah
</domain>
bar
<domain gmail.com>
blah
</domain>
baz
END
foo
<domail yahoo.com>
blah
blah
</domain>
qux
#<domain hotmail.com>
#blah
#blah
#blah
#</domain>
bar
<domain gmail.com>
blah
</domain>
baz
This might work for you (GNU sed):
sed '/^<domain hotmail.com>$/{:a;N;/^<\/domain>$/M!ba;s/^/#/Mg} file
This will comment the tags and the values between if and only if both tags exist.
sed 's/^/#/'
Example:
sdlcb#ubuntu:~/AMD_C$ cat file
<domain hotmail.com>
blah
blah
blah
</domain>
sdlcb#ubuntu:~/AMD_C$ sed 's/^/#/' file
#<domain hotmail.com>
#blah
#blah
#blah
#</domain>

Perl conditional extraction of lines from file

Could anyone suggest me a method where I could extract a few lines of text while reading it.
file sample structure:
A blah blah string1
B blah blah
C blah string2
D blah string3 blah
E blah blah
F blah string2
G blah string3 blah
H blah blah string1
I blah blah
J blah string2
Here I want to extract lines starting with string "string1" followed/ended by "string2"
In effect I want lines A-C and H-J in the above example.
My experiments are failing with the presence of line F which I would want to ignore.
Perl one liner and the Flip-flop Operator ..:
$ perl -ne 'print if /\bstring1\b/ .. /\bstring2\b/' file
A blah blah string1
B blah blah
C blah string2
H blah blah string1
I blah blah
J blah string2
\b in the above regex is called word boundary. It matches between a word characetr and a non word character.
From Perl --help
-n assume "while (<>) { ... }" loop around program
-e program one line of program (several -e's allowed, omit programfile)
This can be done as well in awk and sed by indicating the patterns between which you want to print the lines:
sed -n '/string1/,/string2/p' file
awk '/string1/,/string2/' file
In Perl you can say:
perl -e 'while (<>){print if (/string1/../string2/);}' file
Which is equivalent to
perl -ne '{print if (/string1/../string2/)}' file
^
All of them return:
A blah blah string1
B blah blah
C blah string2
H blah blah string1
I blah blah
J blah string2

how to find specific lines when it hits a certain pattern

whenever it see a pattern of ; and abc[0] i need to print first line just after ; and a line which contain abc[0].
i have something like this
blah blah;
blah blah blah;
xyz blah blah,
blah blah
abc[2]
abc[1],
abc[0]
blah blah,
blah blah
abc[1],
abc[0]
blah blah
blah blah;
pqr blah blah
blah blah blah
abc[0]
required output is as shown below
xyz blah blah,
abc[0]
pqr blah blah
abc[0]
Thanks.
awk '/;/ { f=1; next } f{ print $0 ; f=0; next} /abc\[0\]/ { print }' inputfile
Explaination:
/;/ { f=1; next } - Set the flag to 1 when you encounter a line with `;` pattern.
Since I believe you want to print the line after the `;` and not one with the `;`
you do next to skip the entire pattern action statements
f{ print $0 ; f=0; next} - If the flag is true, you print the line, set the flag to false
and skip the rest.
/abc\[0\]/ { print } - If you find the second pattern you print it.
Using GNU Grep
With the input from your question stored as /tmp/corpus, the following will provide the correct output by filtering out context lines.
{ egrep -A1 ';|abc\[0\]' | egrep -v ';|^--'; } < /tmp/corpus
If you have GNU Grep, but your shell isn't Bash or doesn't support the redirection as above, the following pipeline is equivalent but (in my opinion) less readable:
egrep -A1 ';|abc\[0\]' /tmp/corpus | egrep -v ';|^--'
Pure GNU sed
sed -n '/;/ {:k n;h; // bk}; /abc\[0\]/ {x ;//! {p;x;p;x}}' file
xyz blah blah,
abc[0]
pqr blah blah
abc[0]

Wrapping each line inside quotation marks with AutoHotkey

I have two thousand lines of text. I need each line to be wrapped inside quotation marks like "example".
Before
line 1
line 2
line 3
After
"line 1"
"line 2"
"line 3"
How could I take care of this with AutoHotkey?
Like this?
text=
(
bla bla bla
blah blah blah blah
blablah blablah blablah
)
MsgBox % RegExReplace(RegExReplace(text,"`am)^.","""$0"),"`am).$","$0""")