echo nested quotation marks in tcsh - echo

I have a tcsh script that generates a text file. One of the lines in the text file is:
bla bla bla 'foo foo foo "bar bar bar"': etc etc;
Note the nested ' and " and also the : and ; that must be there.
The : and ; require the whole string to be surrounded by quotation marks. However, if I do that, I have trouble escaping the quotation marks.
The command is:
echo "bla bla bla 'foo foo foo "bar bar bar"': etc etc;" >> outfile
How can I escape the quotation marks around bar bar bar so that they get printed correctly?

echo "bla bla bla 'foo foo foo "\""bar bar bar"\""': etc etc;"
or this:
echo "bla bla bla 'foo foo foo "\"bar bar bar\""': etc etc;"
These should work for the simple example you gave, but may not help for what you're actually trying to do... Quoting in tcsh always annoyed me, especially when trying to define aliases with a mix of back-ticks, quotes, and double-qutes.
Be warned that the second form works for echo, but it actually creates three separate arguments on the command line, which are (after interpreting the escape sequences):
bla bla bla 'foo foo foo "bar
bar
bar"': etc etc;
The first form is the one you should use.

Related

SED: Combine text between two pattern in same line

I m trying to use sed /awk command to parse my text file.
I want to print text between two pattern in same line with some character added in it.
ex:
If my line is
uint8_t aucRepresentationName[NR_UNIT_REPRESENTATIONS][CHARS_P_REPRESENTATION];
OR
uint8_t aucRepresentationName [NR_UNIT_REPRESENTATIONS] [CHARS_P_REPRESENTATION];
I want to print NR_UNIT_REPRESENTATIONS*CHARS_P_REPRESENTATION
So , I have stared with sed command to insert line deliminter \n after '[' , deviding line in suitable species and then tried to parse it again.
echo "bla bla bla [AK] bla bla bla bla [A_K] bla bla bla" | sed 's/\[/\n&/g;' | awk '{sub(/.*\[ /,"");sub(/\].*/,"");print;}'
echo "bla bla bla [AK] bla bla bla bla [A_K] bla bla bla" | sed 's/\[/\n&/g;' | sed -e 's/^.*\[ //g;s/ \].*$//g'
And it is not always two diamensional array, it could be none or single/double dimentional array, I need to first how many instance of [], if its 0 then write 1, if its single diamensional array then ex A[SIZE] then write SIZE its two diamensional array ex:A[RAW][COL] write RAW*COL..
I would like to know what is wrong in my command? or any other option to do it as it will help me to further study sed.
Amruta
Try:
awk -F '[][]' '{print $2,$4}' OFS=\* file
OK, if it is a single occurrence of 0,1 or two-dimensional in one page you could try:
awk -F '[][]' '{if(NF==3)print $2; else if(NF>4)print $2,$4; else print 1}' OFS=\* file
or less comprehensible ;) :
awk -F '[][]' '{$0=NF==3?$2:NF>4?$2 OFS $4:1}1' OFS=\* file
use this:
perl -lne 'push #a,/\[([^\]]*)\]/g;END{print join "*",#a}'
modified from here
tested below:
> echo "bla [AK] bla [A_K] 10" | perl -lne 'push #a,/\[([^\]]*)\]/g;END{print join "*",#a}'
AK*A_K
You can try the following:
echo "bla bla bla [AK] bla bla bla bla [A_K] bla bla bla" | sed 's/.*\[\(.*\)\].*\[\(.*\)\].*/\1*\2/g'
AK*A_K
With sed:
sed -n 's/[^]]*\[\([^]]*\)\]\s*\[\([^]]*\)\].*$/\1*\2/p' input

Perl Search and Capture Line After

Alright, so this is probably a pretty easy question to answer, but I'm struggling with it. I'm trying to get my program to capture everything after a certain word and then print it. For example, if the input text is
bar foo foo foo foo
Then I want the output to be "foo foo foo foo" if I am searching for bar. I hope my question makes sense. Any help would be greatly appreciated! I'm very new to perl, so the more explanation you can give, the better. Thank you!
#! /usr/bin/env perl
*ARGV = *DATA; # for demo only
while (<>) {
print "line $.: $1\n" if /bar\s+(.+)/;
}
__DATA__
you can't see me
bar foo foo foo foo
nope
Output:
line 2: foo foo foo foo

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""")

How can I escape an arbitrary string for use as a command line argument in Bash?

I have a list of strings and I want to pass those strings as arguments in a single Bash command line call. For simple alphanumeric strings it suffices to just pass them verbatim:
> script.pl foo bar baz yes no
foo
bar
baz
yes
no
I understand that if an argument contains spaces or backslashes or double-quotes, I need to backslash-escape the double-quotes and backslashes, and then double-quote the argument.
> script.pl foo bar baz "\"yes\"\\\"no\""
foo
bar
baz
"yes"\"no"
But when an argument contains an exclamation mark, this happens:
> script.pl !foo
-bash: !foo: event not found
Double quoting doesn't work:
> script.pl "!foo"
-bash: !foo: event not found
Nor does backslash-escaping (notice how the literal backslash is present in the output):
> script.pl "\!foo"
\!foo
I don't know much about Bash yet but I know that there are other special characters which do similar things. What is the general procedure for safely escaping an arbitrary string for use as a command line argument in Bash? Let's assume the string can be of arbitrary length and contain arbitrary combinations of special characters. I would like an escape() subroutine that I can use as below (Perl example):
$cmd = join " ", map { escape($_); } #args;
Here are some more example strings which should be safely escaped by this function (I know some of these look Windows-like, that's deliberate):
yes
no
Hello, world [string with a comma and space in it]
C:\Program Files\ [path with backslashes and a space in it]
" [i.e. a double-quote]
\ [backslash]
\\ [two backslashes]
\\\ [three backslashes]
\\\\ [four backslashes]
\\\\\ [five backslashes]
"\ [double-quote, backslash]
"\T [double-quote, backslash, T]
"\\T [double-quote, backslash, backslash, T]
!1
!A
"!\/'" [double-quote, exclamation, backslash, forward slash, apostrophe, double quote]
"Jeff's!" [double-quote, J, e, f, f, apostrophe, s, exclamation, double quote]
$PATH
%PATH%
&
<>|&^
*#$$A$##?-_
EDIT:
Would this do the trick? Escape every unusual character with a backslash, and omit single or double quotes. (Example is in Perl but any language can do this)
sub escape {
$_[0] =~ s/([^a-zA-Z0-9_])/\\$1/g;
return $_[0];
}
If you want to securely quote anything for Bash, you can use its built-in printf %q formatting:
cat strings.txt:
yes
no
Hello, world
C:\Program Files\
"
\
\\
\\\
\\\\
\\\\\
"\
"\T
"\\T
!1
!A
"!\/'"
"Jeff's!"
$PATH
%PATH%
&
<>|&^
*#$$A$##?-_
cat quote.sh:
#!/bin/bash
while IFS= read -r string
do
printf '%q\n' "$string"
done < strings.txt
./quote.sh:
yes
no
Hello\,\ world
C:\\Program\ Files\\
\"
\\
\\\\
\\\\\\
\\\\\\\\
\\\\\\\\\\
\"\\
\"\\T
\"\\\\T
\!1
\!A
\"\!\\/\'\"
\"Jeff\'s\!\"
\$PATH
%PATH%
\&
\<\>\|\&\^
\*#\$\$A\$##\?-_
These strings can be copied verbatim to for example echo to output the original strings in strings.txt.
What is the general procedure for safely escaping an arbitrary string for use as a command line argument in Bash?
Replace every occurrence of ' with '\'', then put ' at the beginning and end.
Every character except for a single quote can be used verbatim in a single-quote-delimited string. There's no way to put a single quote inside a single-quote-delimited string, but that's easy enough to work around: end the string ('), then add a single quote by using a backslash to escape it (\'), then begin a new string (').
As far as I know, this will always work, with no exceptions.
You can use single quotes to escape strings for Bash. Note however this does not expand variables within quotes as double quotes do. In your example, the following should work:
script.pl '!foo'
From Perl, this depends on the function you are using to spawn the external process. For example, if you use the system function, you can pass arguments as parameters so there"s no need to escape them. Of course you"d still need to escape quotes for Perl:
system("/usr/bin/rm", "-fr", "/tmp/CGI_test", "/var/tmp/CGI");
sub text_to_shell_lit(_) {
return $_[0] if $_[0] =~ /^[a-zA-Z0-9_\-]+\z/;
my $s = $_[0];
$s =~ s/'/'\\''/g;
return "'$s'";
}
See this earlier post for an example.
Whenever you see you don't get the desired output, use the following method:
"""\special character"""
where special character may include ! " * ^ % $ # # ....
For instance, if you want to create a bash generating another bash file in which there is a string and you want to assign a value to that, you can have the following sample scenario:
Area="(1250,600),(1400,750)"
printf "SubArea="""\""""${Area}"""\""""\n" > test.sh
printf "echo """\$"""{SubArea}" >> test.sh
Then test.sh file will have the following code:
SubArea="(1250,600),(1400,750)"
echo ${SubArea}
As a reminder to have newline \n, we should use printf.
Bash interprets exclamation marks only in interactive mode.
You can prevent this by doing:
set +o histexpand
Inside double quotes you must escape dollar signs, double quotes, backslashes and I would say that's all.
This is not a complete answer, but I find it useful sometimes to combine two types of quote for a single string by concatenating them, for example echo "$HOME"'/foo!?.*' .
FWIW, I wrote this function that invokes a set of arguments using different credentials. The su command required serializing all the arguments, which required escaping them all, which I did with the printf idiom suggested above.
$ escape_args_then_call_as myname whoami
escape_args_then_call_as() {
local user=$1
shift
local -a args
for i in "$#"; do
args+=( $(printf %q "${i}") )
done
sudo su "${user}" -c "${args[*]}"
}

sed/awk + line manipulation

I have two different questions(on both questions need to ignore spaces)
How to print all lines until "=" separator for example
echo " bla bla girl man dog = black white color bla 123 4" | sed/awk .....
Will print:
bla bla girl man dog
the second question
How to print all lines from "=" until end of line
echo " bla bla girl man dof = black white color bla 123 4" | sed/awk .....
Will print
black white color bla 123 4
THX for help
Lidia
You can try this:
echo " bla bla girl man dog = black white color bla 123 4" | awk -F '=' '{print $1}'
cut can help you.
cut cuts a line using a custom delimiter, and gives you any parts around it.
echo " bla bla girl man dof = black white color bla 123 4" | cut -d= -f1 gives you the first part before a =
echo " bla bla girl man dof = black white color bla 123 4" | cut -d= -f2 gives you the second part after a =
if you have more than one = one the line -f2- will give you everything after the first = (ignoring the second =).
Answer to the first question:
sed 's/^ *\([^=]*\) *= *\(.*\) *$/\1/'
Answer to the second question:
sed 's/^ *\([^=]*\) *= *\(.*\) *$/\2/'
Explanation:
^ *\([^=]*\) *= *\(.*\) *$ matches the whole line. It contains two capturing groups: first group captures everything up to the first = except boundary spaces, second group captures everything after the first = except for boundary spaces. \1 and \2 are references to the capturing groups.
EDIT The above answer to the first question is incorrect, as it leaves trailing spaces. A correct version should read:
sed 's/^ *\([^=]*\) *= *\(.*\) *$/\1/' | sed 's/ *$//'
There seems to be no way to make the [^=]* reluctant, hence two sed commands.
For the first, use
cut -d= -f1
For the second, use
cut -d= -f2-
But these solutions preserve spaces.
With sed:
First question:
echo " bla bla girl man dog = black white color bla 123 4" | sed -n '{s/\([^=]*\)=.*/\1/p}'
Second question:
echo " bla bla girl man dog = black white color bla 123 4" | sed -n '{s/[^=]*=\(.*\)/\1/p}'
With awk:
First question:
echo " bla bla girl man dog = black white color bla 123 4" | awk -F= '{print $1}'
Second quetion:
if you have exactly one = in each line:
echo " bla bla girl man dog = black white color bla 123 4" | awk -F= '{print $2}'
Using cut
echo " bla bla girl man dog = black white color bla 123 4" | cut -d= -f1
With Atmark its much more easy:
first
# split = head trim_
second
# split = tail trim_