Combining multiline variables as columns in bash - bash

I have to multi-line string variables each with an equal number of lines. I'm trying to make each a column of a new variable called seqinfo, but I am getting a syntax error. Any idea what the problem is?
Code:
seqinfo=$(paste <(echo "$var1") <(echo "$var2"))
Error message:
command substitution: line 13: syntax error near unexpected token `('
command substitution: line 13: `paste <(echo "$var1") <(echo "$var2"))'

You can simply do it like this :
var1='
some
fruits
now'
var2='
even
more
lines'
echo "${var1}${var2}"
Output
some
fruits
now
even
more
lines
Regards!

Related

logical or | Unix

I'm trying to realize a simple shell program that display french phone numbers contained in a file.
Here is my basic shell
#!/bin/bash
#search of phone numbers
t=( \+ | 00 )33[1-9][0-9]{8}
t2=( \+ | 00 )33[1-9][0-9]-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}
t3=( \+ | 00 )33[1-9][0-9].[0-9]{2}.[0-9]{2}.[0-9]{2}.[0-9]{2}
grep -e $1 ( $t | $t2 | $t3 )
Here is my input file :
phone_number.txt
+33143730862
00335.45.45.45.45
+332-45-45-45-45
+334545454554454545
I keep getting this errors :
./script_exo2.sh: line 5: syntax error near unexpected token `|'
./script_exo2.sh: line 5: `t=( \+ | 00 )33[1-9][0-9]{8}'
./script_exo2.sh: line 6: syntax error near unexpected token `|'
./script_exo2.sh: line 6: `t2=( \+ | 00 )33[1-9][0-9]-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}'
./script_exo2.sh: line 7: syntax error near unexpected token `|'
./script_exo2.sh: line 7: `t3=( \+ | 00 )33[1-9][0-9].[0-9]{2}.[0-9]{2}.[0-9]{2}.[0-9]{2}'
./script_exo2.sh: line 9: syntax error near unexpected token `('
./script_exo2.sh: line 9: `grep -e $1 ( $t | $t2 | $t3 )'
Your t2 and t3 have one more digit than the samples you're trying to match. Also, you need to quote the arguments, and get rid of those spaces:
#!/bin/sh
t='(\+|00)33[1-9][0-9]{8}'
t2='(\+|00)33[1-9]-[0-9]{2}-[0-9]{2}-[0-9]{2}-[0-9]{2}'
t3='(\+|00)33[1-9]\.[0-9]{2}\.[0-9]{2}\.[0-9]{2}\.[0-9]{2}'
exec grep -E -e "$t|$t2|$t3" "$#"
I've used sh instead of bash, as we're not using any Bash features not available in standard POSIX shells (e.g. dash).
I've used single quotes above for the definitions of t, t1 and t2, and double quotes where they are to be substituted.
I've told grep to understand Extended Regular Expressions via the -E flag, and I've put the pattern as the argument to the -e ("expression") flag to grep.
The grep process execs in place of the shell, as there is no reason to fork for it.
I've passed the full set of input arguments "$#" so you can give extra options to grep (such as -w, -n or -o, for example), and choose whether to supply a file or stream stdin to your script.
Note also that if you're willing to accept a mix of ., - or nothing separating digit pairs, you can simplify your three expressions to just one:
(\+|00)33[1-9][0-9]([-.]?[0-9]{2}){4}
and the script becomes
#!/bin/bash
exec grep -E -e '(\+|00)33[1-9]([-.]?[0-9]{2}){4}' "$#"
If you need the delimiters to match, then you can use a capture group for that:
#!/bin/bash
exec grep -E -e '(\+|00)33[1-9]([-.]?)[0-9]{2}(\2[0-9]{2}){3}' "$#"

Unable to define line number in sed by variable

I'm trying to use an array to define the lines to replace using sed; I can delete the lines using a variable for the line number but I can't get sed to use the variable to define the line number to write to. The problem seems to reside in the insert line. How do you pass the value of an array as a line number to sed?
#!/bin/bash
lineNum=$(sed -n '/max_allowed_packet/=' /etc/mysql/my.cnf)
IFS= #There's a space as the delimiter#
ary=($lineNum)
#for key in "${!ary[#]}";
# do
# sed -i '$ary[$key]'d /etc/mysql/my.cnf;
# #The folllowing line errors#
# sed -i "'$ary[$key]'imax_allowed_packet = 32M" /etc/mysql/my.cnf;
# #The above line errors#
#done
#for val in "${ary[#]}";
# do
# sed -i "${val}d" /etc/mysql/my.cnf;
# sed -i "${val}imax_allowed_packet = 32M" /etc/mysql/my.cnf;
# done
for val in "${ary[#]}";
do
sed -i "${val}s/.*/imax_allowed_packet = 32M" /etc/mysql/my.cnf";
done
For the first stanza of script I get the following output:
Error: sed: -e expression #1, char 1: unknown command: `''
For the second Stanza I get the following output:
sed: -e expression #1, char 3: unknown command:
'
sed: -e expression #1, char 3: unknown command:
'
For the third Stanza I get the following output:
./test.sh: line 22: unexpected EOF while looking for matching `"'
./test.sh: line 24: syntax error: unexpected end of file
Edit, rewriting the sed commands as sed -i "${ary[$key]}" generates the following error output: sed: -e expression #1, char 3: unknown command: `
I think you're over-complicating the issue. Your script can be reduced to this:
sed 's/\(max_allowed_packet\).*/\1 = 32M/' /etc/mysql.cnf
This performs a substitution on every occurrence of max_allowed_packet, setting the rest of the line to = 32M. Add the -i switch to overwrite the file when you're happy with the result.
Problems with your attempt
Shell parameters are not expanded within single quotes, so you would need to use double quotes, e.g. sed -i "${ary[$key]}d". You can use set -x to see what is happening here - at the moment, you will see the literal string $ary[$key], rather than the array value.
If I understand your intention correctly (you want to substitute the entire line), there's no need to call sed twice:
for val in "${ary[#]}"; do
sed -i.bak "${val}s/.*/imax_allowed_packet = 32M" /etc/mysql/my.cnf
done
I have chosen to loop through the values of the array, instead of the keys, in order to simplify things a little. When using the -i option, it is always a good idea to specify a backup file, as I have done.

Net::OpenSSH command remote with multi pipeline

i have a problem when attempt run multi command in remote linux, with Perl and Module Net::OpenSSH. .
use Net::OpenSSH;
my $new_connect = Net::OpenSSH->new($D_CONNECT{'HOST'}, %OPT);
my $file = "file.log.gz"
my ($output2, $error2) = $new_connect->capture({ timeout => 10 }, "gunzip -c /path/to/file/$file | tail -n1 | awk '/successfully completed/ {print \$NF}'");
the output that i get is:
bash: -c: line 1: syntax error near unexpected token |'
bash: -c: line 1: |tail -n1 |awk '/successfully completed/ {print $NF}''
;;;
any idea or suggestion, thanks.
Fcs
Probably a quoting error. Just let Net::OpenSSH take care of the quoting for you:
my ($output2, $error2) = $new_connect->capture({ timeout => 10 },
'gunzip', '-c', "/path/to/file/$file", \\'|',
'tail', '-n1', \\'|',
'awk', '/successfully completed/ {print $NF}');
Note how the pipes (|) are passed as a double reference so that they are passed unquoted to the remote shell. The module documentation has a section on quoting.
That looks like the error message you'd get if you had a newline at the end of your $file string, causing the pipe character to be at the start of a second line (interpreted as the start of a second command).
This test deomstrates the same error:
bash -c 'echo foo
| cat'
So I guess your bug doesn't really occur with $file = "file.log.gz" and whatever your real $file is, you need to chomp it.
A bigger mystery is why bash says the error is on line 1 of the -c. ash, ksh, and zsh all correctly report it on line 2.

unexpected EOF while looking for matching `'' while using sed

Yes this question has been asked many times, and in the answer it is said to us \ escape character before the single quote.
In the below code it isn't working:
LIST="(96634,IV14075295,TR14075685')"
LIST=`echo $LIST | sed 's/,/AAA/g' `
echo $LIST # Output: (96634AAAIV14075295AAATR14075685')
# Now i want to quote the list elements
LIST=`echo $LIST | sed 's/,/\',\'/g' ` # Giving error
# exit 0
Error :
line 7: unexpected EOF while looking for matching `''
line 8: syntax error: unexpected end of file
Instead of single quotes, use double quotes in sed command, and also remove the space before last backtick. If there is single quote present in the sed pattern then use an alternative enclosing quotes(ie, double quotes),
sed "s/,/\',\'/g"
And the line would be,
LIST=$(echo $LIST | sed "s/,/\',\'/g")
Don't use backticks inside the sripts instead of bacticks, use $()
You can use awk
echo $LIST
(96634,IV14075295,TR14075685')
LIST=$(awk '{gsub(/,/,q"&"q)};gsub(/\(/,"&"q)1' q="'" <<< $LIST)
echo $LIST
('96634','IV14075295','TR14075685')
To prevent problems with the single quote, I just set it to an awk variable.
consider
LIST="$(sed "s/,/\',\'/g" <<< "$LIST")"
but first and last elements probably won't get quoted completely, because of missing leading and trailing comma
btw, you don't need to subshell to sed - string matching and substitution is entirely within the capabilities of bash:
LIST="${LIST//,/\',\'}"

How to store awk that has multiple backslashes as a variable?

I'm new to bashes but learning quickly. One thing that stumps me is how to store an awk output as a variable if it contains multiple backslashs. I have awk code to tell me everything between the two terms "1\1\" and "\#" (quotation marks not included). I put an extra backslash behind each backslash. The echo command works fine:
#!/bin/
FILENAME=$1
$echo awk '/1\\1\\/,/\\\\#/' $FILENAME
I try to store it as a variable via the regular way:
VAR=$($echo awk '/1\\1\\/,/\\\\#/' $FILENAME)
echo $VAR
I get a totally different section of the text file I'm analyzing. I figure that the parentheses alter the meaning of a backslash, but I can't seem to find a way to store the string I am getting as a variable without using parentheses. Any suggestions? Thanks!
Edit: A major portion of the input file:
Atom 3 needs variable 1= 1.4272969666 but is 0.9695781041
Input z-matrix variables are not compatible with final structure.
1\1\CRUNTCH-C1950-1-9\FOpt\RB3LYP\CC-pVTZ\H2O3\DK0178\21-Nov-2013\0\\#
p B3LYP/CC-PVTZ opt\\Peroxide Molecule\\0,1\H,-0.2455786307,0.24093160
48,0.0173467521\O,-0.1623823861,-0.3287313,0.7975033131\O,1.2337882601
,-0.2361247615,1.0791204051\O,1.4541296394,0.9715988133,1.8071520489\H
,1.2170466675,0.7056779744,2.7089056027\\Version=EM64L-G09RevB.01\Stat
e=1-A\HF=-226.7854316\RMSD=3.950e-09\RMSF=2.016e-05\Dipole=-0.2755823,
0.261353,0.1046274\Quadrupole=-1.3992237,-2.043705,3.4429287,-1.030514
,1.5582408,-0.1409701\PG=C02 [C2(O1),X(H2O2)]\\#
ALL SCIENCE IS EITHER PHYSICS, OR STAMP COLLECTING.
The part I get the first time:
1\1\CRUNTCH-C1950-1-9\FOpt\RB3LYP\CC-pVTZ\H2O3\DK0178\21-Nov-2013\0\\#
p B3LYP/CC-PVTZ opt\\Peroxide Molecule\\0,1\H,-0.2455786307,0.24093160
48,0.0173467521\O,-0.1623823861,-0.3287313,0.7975033131\O,1.2337882601
,-0.2361247615,1.0791204051\O,1.4541296394,0.9715988133,1.8071520489\H
,1.2170466675,0.7056779744,2.7089056027\\Version=EM64L-G09RevB.01\Stat
e=1-A\HF=-226.7854316\RMSD=3.950e-09\RMSF=2.016e-05\Dipole=-0.2755823,
0.261353,0.1046274\Quadrupole=-1.3992237,-2.043705,3.4429287,-1.030514
,1.5582408,-0.1409701\PG=C02 [C2(O1),X(H2O2)]\\#
The part I get the second time:
,1.5582408,-0.1409701\PG=C02 [C2(O1),X(H2O2)]\#05,3.4429287,-1.030514
Thanks!
Edit 2 (Sorry this is getting rather long) The code and error message I got for answer 2:
Input code:
#!/bin/
file=$1
$ cat file
abc
1\1\
def
\#
ghi
$ awk '/1\\1\\/{f=1} f; /\\#/{f=0}' file
1\1\
def
\#
$ var=$(awk '/1\\1\\/{f=1} f; /\\#/{f=0}' file)
$ printf "%s\n" "$var"
1\1\
def
\#
Error:
[dave#server ~]$ bash sshell.sh peroxide.out
sshell.sh: line 5: $: command not found
sshell.sh: line 6: abc: command not found
sshell.sh: line 8: 11def: command not found
sshell.sh: line 9: #: command not found
sshell.sh: line 10: ghi: command not found
sshell.sh: line 12: $: command not found
sshell.sh: line 14: 11def: command not found
sshell.sh: line 15: #: command not found
awk: cmd. line:1: fatal: cannot open file `file' for reading (No such file or directory)
sshell.sh: line 17: $: command not found
sshell.sh: line 18: $: command not found
sshell.sh: line 20: 11def: command not found
sshell.sh: line 21: #: command not found
Let's start with this:
$ cat file
abc
1\1\
def
\#
ghi
$ awk '/1\\1\\/{f=1} f; /\\#/{f=0}' file
1\1\
def
\#
$ var=$(awk '/1\\1\\/{f=1} f; /\\#/{f=0}' file)
$ printf "%s\n" "$var"
1\1\
def
\#
Now - if that's not exactly what you want, update your question to include some sample input and expected output.
Don't ever use awk '/start/,/end/' as it makes trivial things like this slightly briefer, but requires a complete re-write for anything even marginally more interesting.
The following works for me:
#! /bin/bash
var=$(awk 'BEGIN { RS="" } {
match($0,/1\\1\\(.*)\\#/,a)
print a[1] }' input.txt)
echo "$var"
where input.txt is your input file..

Resources