I have the following command:
echo "exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" |
/home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh |
grep "^| Row_2" |
awk '{print $15 }'
which only works with echo in the front. I tried to set this line into a variable. I've tried quotations marks, parenthesis, and back ticks, with no luck.
May anyone tell me the correct syntax for setting this into a variable?
If you want more columns store in an array you should use this syntax (it is also good if you have only one result):
#!/bin/bash
result=( $( echo "exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" |
/home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh |
grep "^| Row_2" |
awk '{print $15 }' ) )
$result=$(exec [loc_ver].[dbo].[sp_RptEmpCheckInOutMissingTime_2]" | /home/mdland_tool/common/bin/run_isql_prod_rpt_2.sh | grep "^| Row_2" | awk '{print $15 })
Since you asked for both meanings of your question:
First, imagine a simpler case:
echo asdf
If you want to execute this command and store the result somewhere, you do the following:
$(echo asdf)
For example:
variable=$(echo asdf)
# or
if [ "$(echo asdf)" == "asdf" ]; then echo good; fi
So generally, $(command) executes command and returns the output.
If you want to store the text of the command itself, you can, well, just do that:
variable='echo asdf'
# or
variable="echo asdf"
# or
variable=echo\ asdf
Different formats depending on the content of your command. So now once you have the variable storing the command, you can simply execute the command with the $(command) syntax. However, pay attention that the command itself is in a variable. Therefore, you would execute the command by:
$($variable)
As a complete example, let's combine both:
command="echo asdf"
result=$($command)
echo $result
Related
I want to transform a string given in this form:
xyx some commands
into this form:
alias xyz="some commands"
I tried different combinations in the terminal. It seems (i'm not sure) that it worked once, but never when i run this from the script. I've read somewhere that this is a variable problem.
Alias for readability:
alias first="sed 's/\s.*//'"
alias rest="sed 's/\S*\s*//'"
cat f_in | tee -a >(one=$(first)) >(two=$(rest)) | tee >(awk '{print "alias "$1"=\""$2"\""}' > f_out )
I used awk in this way to parse "cat f_in" into "print". It doesn't work. Then, i used "awk -v" but it still doesn't work too. How to redirect variable $one and $two into awk:
{one=$(first) === first | read -r one }?
Is this what you're trying to do:
$ echo 'xyx some commands' |
awk '{var=$1; sub(/^[^[:space:]]+[[:space:]]+/,""); printf "alias %s=\"%s\"\n", var, $0}'
alias xyx="some commands"
$ echo 'xyx some commands' |
sed 's/\([^[:space:]]*\)[[:space:]]*\(.*\)/alias \1="\2"/'
alias xyx="some commands"
I'm processing a file by line, so my shell script is this:
check_vm_connectivity()
{
$res=`cat temp.txt` # this is line 10
i=0
for line in "$res"
do
i=$i+1
if [[ $i -gt 3 ]] ; then
continue
fi
echo "${line}"
done
}
The temp.txt is this:
+--------------------------------------+
| ID |
+--------------------------------------+
| cb91a52f-f0dd-443a-adfe-84c5c685d9b3 |
| 184564aa-9a7d-48ef-b8f0-ff9d51987e71 |
| f01f9739-c7a7-404c-8789-4e3e2edf314e |
| 825925cc-a816-4434-8b4b-a75301ddaefd |
when I run script, report this:
vm_connectivity.sh: line 10: =+--------------------------------------+: command not found
Why? How to fix this bug? Thank you~
May i ask why you are using
$res=`cat temp.txt`?
shouldn't it be
res=`cat temp.txt`
variables in a shell are set with var= rather than $var=
res is empty when you're entering the function, so that line
expands to the empty string, followed by an equals sign,
followed by the contents of temp.txt. The shell then interprets
that, and since a command is terminated by a newline, and
=+--------------------------------------+ has the syntax
of a command, rather than anything else, the shell tries to
run it as such.
You want: res=$(cat temp.txt)
However, it looks like you're trying to output
the first three lines, in which case just
do
head -n3 temp.txt
though from the looks of it, you probably want all except the first three
lines:
tail -n +4 temp.txt
and if you're looking for just the uuids:
tail -n +4 temp.txt | awk '{print $2}'
I used many times [``] to capture output of command to a variable. but with following code i am not getting right output.
#!/bin/bash
export XLINE='($ZWP_SCRIP_NAME),$ZWP_LT_RSI_TRIGGER)R),$ZWP_RTIMER'
echo 'Original XLINE'
echo $XLINE
echo '------------------'
echo 'Extract all word with $ZWP'
#works fine
echo $XLINE | sed -e 's/\$/\n/g' | sed -e 's/.*\(ZWP[_A-Z]*\).*/\1/g' | grep ZWP
echo '------------------'
echo 'Assign all word with $ZWP to XVAR'
#XVAR doesn't get all the values
export XVAR=`echo $XLINE | sed -e 's/\$/\n/g' | sed -e 's/.*\(ZWP[_A-Z]*\).*/\1/g' | grep ZWP` #fails
echo "$XVAR"
and i get:
Original XLINE
($ZWP_SCRIP_NAME),$ZWP_LT_RSI_TRIGGER)R),$ZWP_RTIMER
------------------
Extract all word with $ZWP
ZWP_SCRIP_NAME
ZWP_LT_RSI_TRIGGER
ZWP_RTIMER
------------------
Assign all word with $ZWP to XVAR
ZWP_RTIMER
why XVAR doesn't get all the values?
however if i use $() to capture the out instead of ``, it works fine. but why `` is not working?
Having GNU grep you can use this command:
XVAR=$(grep -oP '\$\KZWP[A-Z_]+' <<< "$XLINE")
If you pass -P grep is using Perl compatible regular expressions. The key here is the \K escape sequence. Basically the regex matches $ZWP followed by one or more uppercase characters or underscores. The \K after the $ removes the $ itself from the match, while its presence is still required to match the whole pattern. Call it poor man's lookbehind if you want, I like it! :)
Btw, grep -o outputs every match on a single line instead of just printing the lines which match the pattern.
If you don't have GNU grep or you care about portability you can use awk, like this:
XVAR=$(awk -F'$' '{sub(/[^A-Z_].*/, "", $2); print $2}' RS=',' <<< "$XLINE")
First, the smallest change that makes your code "work":
echo "$XLINE" | tr '$' '\n' | sed -e 's/.*\(ZWP[_A-Z]*\).*/\1/g' | grep ZWP_
The use of tr replaces a sed expression that didn't actually do what you thought it did -- try looking at its output to see.
One sane alternative would be to rely on GNU grep's -o option. If you can't do that...
zwpvars=( ) # create a shell array
zwp_assignment_re='[$](ZWP_[[:alnum:]_]+)(.*)' # ...and a regex
content="$XLINE"
while [[ $content =~ $zwp_assignment_re ]]; do
zwpvars+=( "${BASH_REMATCH[1]}" ) # found a reference
content=${BASH_REMATCH[2]} # stuff the remaining content aside
done
printf 'Found variable: %s\n' "${zwpvars[#]}"
I'm developing a little script using ash shell (not bash).
Now i have a variable with the following composition:
VARIABLE = "number string status"
where number could be any number (actually between 1 and 18 but in the future that number could be higher) the string is a name and status is or on or off
The name usually is only lowercase letter.
Now my problem is to read only the string content in the variable, removing the number and the status.
How i can obtain that?
Two ways; one is to leverage $IFS and use a while loop - this will work for a single line quite happily - as:
echo "Part1 Part2 Part3" | while read a b c
do
echo $a
done
alternatively, use cut as follows:
a=`echo $var | cut -d' ' -f2`
echo $a
How about using cut?
name=$(echo "$variable" | cut -d " " -f 2)
UPDATE
Apparently, Ash doesn't understand $(...). Hopefully you can do this instead:
name=`echo "$variable" | cut -d " " -f 2`
How about :
name=$(echo "$variable" | awk '{print $2}')
#!/bin/sh
myvar="word1 word2 word3 wordX"
set -- $myvar
echo ${15} # outputs word 15
I would like to use the lines coming from 'wc' as variables. For example:
echo 'foo bar' > file.txt
echo 'blah blah blah' >> file.txt
wc file.txt
2 5 23 file.txt
I would like to have something like $lines, $words and $characters associated to the values 2, 5, and 23. How can I do that in bash?
In pure bash: (no awk)
a=($(wc file.txt))
lines=${a[0]}
words=${a[1]}
chars=${a[2]}
This works by using bash's arrays. a=(1 2 3) creates an array with elements 1, 2 and 3. We can then access separate elements with the ${a[indice]} syntax.
Alternative: (based on gonvaled solution)
read lines words chars <<< $(wc x)
Or in sh:
a=$(wc file.txt)
lines=$(echo $a|cut -d' ' -f1)
words=$(echo $a|cut -d' ' -f2)
chars=$(echo $a|cut -d' ' -f3)
There are other solutions but a simple one which I usually use is to put the output of wc in a temporary file, and then read from there:
wc file.txt > xxx
read lines words characters filename < xxx
echo "lines=$lines words=$words characters=$characters filename=$filename"
lines=2 words=5 characters=23 filename=file.txt
The advantage of this method is that you do not need to create several awk processes, one for each variable. The disadvantage is that you need a temporary file, which you should delete afterwards.
Be careful: this does not work:
wc file.txt | read lines words characters filename
The problem is that piping to read creates another process, and the variables are updated there, so they are not accessible in the calling shell.
Edit: adding solution by arnaud576875:
read lines words chars filename <<< $(wc x)
Works without writing to a file (and do not have pipe problem). It is bash specific.
From the bash manual:
Here Strings
A variant of here documents, the format is:
<<<word
The word is expanded and supplied to the command on its standard input.
The key is the "word is expanded" bit.
lines=`wc file.txt | awk '{print $1}'`
words=`wc file.txt | awk '{print $2}'`
...
you can also store the wc result somewhere first.. and then parse it.. if you're picky about performance :)
Just to add another variant --
set -- `wc file.txt`
chars=$1
words=$2
lines=$3
This obviously clobbers $* and related variables. Unlike some of the other solutions here, it is portable to other Bourne shells.
I wanted to store the number of csv file in a variable. The following worked for me:
CSV_COUNT=$(ls ./pathToSubdirectory | grep ".csv" | wc -l | xargs)
xargs removes the whitespace from the wc command
I ran this bash script not in the same folder as the csv files. Thus, the pathToSubdirectory
You can assign output to a variable by opening a sub shell:
$ x=$(wc some-file)
$ echo $x
1 6 60 some-file
Now, in order to get the separate variables, the simplest option is to use awk:
$ x=$(wc some-file | awk '{print $1}')
$ echo $x
1
declare -a result
result=( $(wc < file.txt) )
lines=${result[0]}
words=${result[1]}
characters=${result[2]}
echo "Lines: $lines, Words: $words, Characters: $characters"