creating a variable from sed output - bash

I am banging my head against the keyboard on this simple piece of code.
#!/bin/bash
connstate="Connected"
vpnstatus=$(/opt/cisco/anyconnect/bin/vpn state | (grep -m 1 'state:'))
echo $vpnstatus
vpnconn=$(echo $vpnstatus | sed -e 's/>>\ state: //g' | sed "s/ //g")
echo "$vpnconn" "$connstate"
if [ "$vpnconn" = "$connstate" ];then
echo $vpnconn
else echo "this script still fails"
fi
echo done
This is the output from the above code:
>> state: Connected
Connected Connected
this script still fails
done
I believe the issue revolves around the vpnconn=$ if I comment that section of code out and fill the variable vpnconn="Connected" this code works fine. Something with how the sed is working on the input from vpnstatus and outputting the results to vpnconn is making what looks like a correct result incorrect when doing the compare in the if then.
I have tried splitting up the vpnconn line into two separate lines and that did not change anything, I took out the sed "s/ //g" and replaced it with a trim -d ' ' and that did not change the results. I know this is something small in this tiny piece of code that I am missing.

Did you try?
vpnconn=$(echo "$vpnstatus" | awk '{print $3}')
Something like:
vpnstatus=$(/opt/cisco/anyconnect/bin/vpn state|grep -m 1 'state:'|awk '{print 3}')
should do the work.

Related

putting strings together (variable plus pipe)

The goal is to use a static variable and combine it with the output of a pipe.
I am looking for an one line solution !
This is an complete overhaul of the written examples, to keep it more clean!
The old post I have removed cause of to mutch noise.
link="http://example.com/"
echo "index.html" > test.file
echo "search.php" >> test.file
echo "login.js" >> test.file
cat test.file | awk 'BEGIN {var=ARGV[1];ARGV[1]=""} {print var, $0}' "$link"
http://example.com/ index.html
http://example.com/ search.php
http://example.com/ login.js
cat test.file | awk -v var="$link" '{print var, $0}'
http://example.com/ index.html
http://example.com/ search.php
http://example.com/ login.js
This looks like what I need, but without the nasty white space in it.
I need that field separation gone!
Option -F'' result in error message.
Adding | tr or | sed to remove the while space seems like error correction to me.
The following solution works so far ...
for string in $(cat test.file)
do
printf "${link}%s\n" "$string"
done
Ouptut:
http://example.com/index.html
http://example.com/search.php
http://example.com/login.js
In a loop I can combine all the output of a pipe with my static variable.
But isn't there a better solution without using a loop ?
It seems approaching the pipe with printf doesn't work by default and I have to put xargs to it.
echo "World" | xargs printf 'Hello %s\n' "$1"
Hello
Hello World
Even then the output is doubled, but why ?
I am still looking for an one line solution !
You pipe something into printf, but printf does not process its standard input. You can easily verify this by doing a
echo x | printf foo%s bar
which just prints foobar, and ignores the x.

Unable to remove spaces between strings from a file

I have a file whose contents are like below.
$ cat test
static2 deploy
TDPlanValidator-Prod
I am trying upload contents from these directories to s3 bucket. The issue is s3 doesnt accept spaces and hence I am getting an error. For this to be done, I am trying to remove space between "static2 deploy". This file will have around 400 entries and some of them will have directories with space in it like "static2 deploy". The script which I have written is not able to do that. The script and the output is below.
for i in `cat test`;do var="$( echo "$i" | tr -d ' ' )"; echo $var;done
static2
deploy
TDPlanValidator-Prod
I have tried sed too but that also doesnt work. I want output as below so that I can push it in s3 bucket
static2deploy
Can someone please help me out here? I have been trying things since yesterday but have been unable to fix it.
You can achieve this by below sed command
echo "static2 deploy" | sed "/static2/s/ //g"
How will it work? sed first search for string static2 and once found it will search for all the spaces in that line and removes them.
So above command will output
static2deploy
But if you try with below:-
echo "static deploy" | sed "/static2/s/ //g"
Output would be
static deploy
So in your case you need to try with below:-
cat test | sed "/static2/s/ //g" > output.txt
Hope this will help.
for i in `cat test` loops over every string in the file and not every line.
This works:
cat test | while read line; do var="$( echo "$line" | tr -d ' ' )"; echo $var; done
or shorter if you only want to print the line:
cat test | while read line; do echo "$line" | tr -d ' '; done
Output:
static2deploy
TDPlanValidator-Prod

While read line do and append to a file

I'm getting confused by this script that I am trying to write. Any help would be appreciated, I searched around and wasn't able to come up with a solution. I'm sure it's right in front of my eyes.
I have a python script that makes an API call which returns a value. I have a file (examplefile.txt) where I would like to submit each of the lines to the python script and save the returned text in test.txt
Here is what I came up with, but isn't working. The script appears to run correctly, and I see all of my submitted values from the exampleFile.txt, but nothing is being saved to the test.txt file
cat exampleFile.txt | while read line; do ./apiCall.py -v $line | cut -f2 -d, > test.txt |; done
Any ideas on how to fix?
ANSWERED THANKS!:
cat exampleFile.txt | while read line; do ./apiCall.py -v $line | cut -f2 -d, >> test.txt |; done
Also could use
while read line; do ./apiCall.py -v $line | cut -f2 -d; done < exampleFile.txt >> test.txt
This is a shell scripting question more than it is a python one. However, I think your issue is " > test.txt" the ">" will start from a blank file each time instead of appending the results. try " >> test.txt"

How to handle variables that contain ";"?

I have a configuration file that contains lines like "hallo;welt;" and i want to do a grep on this file.
Whenever i try something like grep "$1;$2" my.config or echo "$1;$2 of even line="$1;$2" my script fails with something like:
: command not found95: line 155: =hallo...
How can i tell bash to ignore ; while evaluating "..." blocks?
EDIT: an example of my code.
# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)
# do some stuff on the permissions
# replace old line with new line
nline="$1;$2;$reads;$writes;$admins"
sed -i "s/$line/$nline/g" $TEMPPERM
my script should be called like this: sh script "table" "a.b.*.>"
EDIT: another, simpler example
$test=$(grep "$1;$2;" temp.authorization.config)
the temp file:
table;pattern;read;write;stuff
the call sh test.sh table pattern results in: : command not foundtable;pattern;read;write;stuff
Don't use $ on the left side of an assignment in bash -- if you do it'll substitute the current value of the variable rather than assigning to it. That is, use:
test=$(grep "$1;$2;" temp.authorization.config)
instead of:
$test=$(grep "$1;$2;" temp.authorization.config)
Edit: also, variable expansions should be in double-quotes unless there's a good reason otherwise. For example, use:
reads=$(echo "$line" | cut -d';' -f3)
instead of:
reads=$(echo $line | cut -d';' -f3)
This doesn't matter for semicolons, but does matter for spaces, wildcards, and a few other things.
A ; inside quotes has no meaning at all for bash. However, if $1 contains a doublequote itself, then you'll end up with
grep "something";$2"
which'll be parsed by bash as two separate commands:
grep "something" ; other"
^---command 1----^ ^----command 2---^
Show please show exactly what your script is doing around the spot the error is occurring, and what data you're feeding into it.
Counter-example:
$ cat file.txt
hello;welt;
hello;world;
hell;welt;
$ cat xx.sh
grep "$1;$2" file.txt
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
$
You have not yet classified your problem accurately.
If you try to assign the result of grep to a variable (like I do) your example breaks.
Please show what you mean. Using the same data file as before and doing an assignment, this is the output I get:
$ cat xx.sh
grep "$1;$2" file.txt
output=$(grep "$1;$2" file.txt)
echo "$output"
$ bash -x xx.sh hello welt
+ grep 'hello;welt' file.txt
hello;welt;
++ grep 'hello;welt' file.txt
+ output='hello;welt;'
+ echo 'hello;welt;'
hello;welt;
$
Seems to work for me. It also demonstrates why the question needs an explicit, complete, executable, minimal example so that we can see what the questioner is doing that is different from what people answering the question think is happening.
I see you've provided some sample code:
# find entry
$line=$(grep "$1;$2;" $PERMISSIONSFILE)
# splitt line
reads=$(echo $line | cut -d';' -f3)
writes=$(echo $line | cut -d';' -f4)
admins=$(echo $line | cut -d';' -f5)
The line $line=$(grep ...) is wrong. You should omit the $ before line. Although it is syntactically correct, it means 'assign to the variable whose name is stored in $line the result of the grep command'. That is unlikely to be what you had in mind. It is, occasionally, useful. However, those occasions are few and far between, and only for people who know what they're doing and who can document accurately what they're doing.
For safety if nothing else, I would also enclose the $line values in double quotes in the echo lines. It may not strictly be necessary, but it is simple protective programming.
The changes lead to:
# find entry
line=$(grep "$1;$2;" $PERMISSIONSFILE)
# split line
reads=$( echo "$line" | cut -d';' -f3)
writes=$(echo "$line" | cut -d';' -f4)
admins=$(echo "$line" | cut -d';' -f5)
The rest of your script was fine.
It seems like you are trying to read a semicolon-delimited file, identify a line starting with 'table;pattern;' where table is a string you specify and pettern is a regular expression grep will understand. Once the line is identified you wish to replaced the 3rd, 4th and 5th fields with different data and write the updated line back to the file.
Does this sound correct?
If so, try this code
#!/bin/bash
in_table="$1"
in_pattern="$2"
file="$3"
while IFS=';' read -r -d$'\n' tuple pattern reads writes admins ; do
line=$(cut -d: -f1<<<"$tuple")
table=$(cut -d: -f2<<<"$tuple")
# do some stuff with the variables
# e.g., update the values
reads=1
writes=2
admins=12345
# replace the old line with the new line
sed -i'' -n $line'{i\
'"$table;$pattern;$reads;$writes;$admins"'
;d;}' "$file"
done < <(grep -n '^'"${in_table}"';'"${in_pattern}"';' "${file}")
I chose to update by line number here to avoid problems of unknown characters in the left hand of the substitution.

bash echo problem

Here's a bash script that extracts some data from a html file.
price=`grep ' <td>\$' $1 | sed -e 's/<td>//g' -e 's:</td>::g' -e 's/\$ //g' -e 's/^ *//g'`
grep ' <td>\$' $1 | sed -e 's/<td>//g' -e 's:</td>::g' -e 's/\$ //g' -e 's/^ *//g'
echo "Price: $price"
The sed part could use some help, but that's not the issue here. The problem is that, when I run the script, it should print the found value twice, right? But it prints it only once, the first time (Without the 'Price:'). What's the problem here?
The problem is that the string you're returning has a \r in it, which returns the cursor to the first column before printing stuff out. Use od -c to verify. And use a proper tool such as xmlstarlet to make sure this doesn't happen.
The first grep reads everything on standard input. Then, the second grep blocks trying to read from stdin.
I'm guessing that unlike the code shown, the assignment actually happens in a subshell and therefore is not visible (lost on exit of subshell)
I'm afraid you ran into a subshell issue that you donot show here. Post more code that you actually use if you can.
--- Sample:
unset price
price=1
echo $price # works
unset price
echo -n 1 | price=$(cat)
echo $price # works _not_
A couple of comments about your use of sed:
-e 's/^ *//g' -- you don't need the "g": your pattern is anchored at the beginning so it can only match once. Might as well look for tabs too: -e 's/^[[:space:]]\{1,\}//'
-e 's/<td>//g' -e 's:</td>::g' can be collapsed into -e 's|</\{0,1\}td>||g'

Resources