Bash script printing a variable value after a newline character - bash

I have bash script which calls another script(some_script). some_script expects some input from the user. I have used printf statement for this purpose.
But the problem is the variable value is not being accepted by the target script. I think this is because '\' is being taken as an escape character in the script
The statement somewhat looks like this
printf 'yes\n$var1\n$var2\n$var3' | some_script
If i directly replace the variable with values it runs perfectly but i want the script to take the values from the variables. How do i achieve this?

There is a difference between " and '. Try
printf "yes\n$var1\n$var2\n$var3" | some_script
because with ' the variables won't get substituted.

Yes, \ is a character that has to be escaped.
Use \\n.
For more details we would need more details on how your script works.

Related

Need to use double code and pass variable in sed command

Searching pattern and displaying with SED which have double code (") and variable need to pass.
Actual log is:
<confirmation ID="123456-109" status>
Want to Print 109
This is with actual sed command which worked :
sed -n 's%.*confirmation="123456-\(.*\)" status.*%\%p' /tmp/log
output: 109
But when I tried use this in script where passing 123456 as variable it is not working.
req_data=`sed -n 's%.*confirmation="$variable-\(.*\)" status.*%\%p' /tmp/log`
When I run in Script is is not giving me any output.
I am expecting output: 109
Execute a command and assign its output to variable res as res="$(command)".
You need to used sed -E to make parenthesis work for grouping (or in normal mode, you have to escape each parenthesis). (note that -E option of sed is not part of the posix standard)
Also, as stated in the comments, variables are not expanded/interpolated inside single quotes. If you are in a single quoted block, terminate that before the variable and start a different block after the variable.
Following should addresses all the above and should solve your problem.
req_data="$(sed -En 's%.*confirmation ID=\\"'$variable'-(.+)\\" status.*%\1%p' /tmp/log)"

shell scripting, setting a variable in awk and taking that out to use with the rest of the script

echo $fbname | awk -F'[__]' '{print $2 $A_name = $2}'
echo $A_name
I am trying to extract a name within the fbname variable like for example,
newlist_sammy_card.csv So I am trying to get the name sammy which is between the two underscores and assign it to a variable I can use for rest of the script.
The first line prints out sammy, which is what I need, but the second line does not.
Can anyone show me where I am not assinging the variable correctly?
There is a fundamental flaw in your understanding and reasoning. If you invoke awk in your script it is spawned as a program in its own individual right. Therefore all the variables that exist in your current shell are not available to awk and vice versa. As such you can not 'define' variables in awk that are then visible to your shell. What you should do is 'capture' the output of awk, by using the notation $(), and assign it to a variable. Consider this example:
var=$(awk '{print "test"}')
echo $var
This will output
test
Now in your case, we are actually facing an xy-problem. You want to extract sammy from the string newlist_sammy_card.csv and use that as a variable. One possible solution in pure bash is the following:
name="newlist_sammy_card.csv"
temp=${name#*_}
var=${temp%%_*}
echo $var
This will output
sammy
There's a LOT of ways to do what you're asking for, e.g. here's a couple more in addition to the other ideas you've received so far:
$ fbname='newlist_sammy_card.csv'
$ A_name=$(echo "$fbname" | cut -d_ -f2)
$ echo "$A_name"
sammy
or:
$ IFS=_
$ set -- $fbname
$ A_name="$2"
$ echo "$A_name"
sammy
but I wonder if you're approaching your problem completely the wrong way. We can't tell without more info on what you're trying to do though.
You can simply use bash:
str1="newlist_sammy_card.csv"
# replace 'newlist_' from front of the string
str2=${str1#*_}
# replace '_card.csv' from back of the string:
str2=${str2%%_*}
echo "$str2" # Output: sammy
Unfortunately it can't be done in a single run in bash. However it should still perform a lot better than launching any kind of external program.
Pankrates's answer explains the problem with the OP's approach well and offers a pure shell solution using shell parameter expansion.
Here's another pure shell solution, using a single command based on the read builtin:
Using bash, with a here-string:
IFS=_ read -r _ A_name _ <<<"$fbname"
POSIX-compliant equivalent, using a here-doc:
IFS=_ read -r _ A_name _ <<EOF
$fbname
EOF
If $fbname contains 'newlist_sammy_card.csv', $A_name will contain 'sammy' afterward.
IFS=_ tells read to split the input into tokens by _ instances.
Note that by directly prepending IFS=... to read, the effect of setting $IFS is localized to the read command - no need to restore the original $IFS later.
read -r _ A_name _ ... reads input unmodified (-r - no interpretation of backslash escape sequences)
Note that _ on either side of A_name is the - customary - name of a dummy variable that is used for input that is of no interest, but is needed to positionally extract the token of interest.
It is a mere coincidence in this case that the name of this dummy variable is the same as the $IFS character.
In this case: $_ receives the 1st field (before the first _ char. in the input), and is then overwritten with any remaining fields after the 2nd field, where the 2nd field is read into the variable of interest, $A_name.

sed partial replace or variable

I'd like to use sed to do a replace, but not by searching for what to replace.
Allow me to explain. I have a variable set to a default value initially.
VARIABLE="DEFAULT"
I can do a sed to replace DEFAULT with what I want, but then I would have to put DEFAULT back when I was all done. This is becuase what gets stored to VARIABLE is unique to the user. I'd like to use sed to search for somthing else other than what to replace. For example, search for VARIABLE=" and " and replace whats between it. That way it just constantly updates and there is no need to reset VARIABLE.
This is how I do it currently:
I call the script and pass an argument
./script 123456789
Inside the script, this is what happens:
sed -i "s%DEFAULT%$1%" file_to_modify
This replaces
VARIABLE="DEFAULT"
with
VARIABLE="123456789"
It would be nice if I didn't have to search for "DEFAULT", because then I would not have to reset VARIABLE at end of script.
sed -r 's/VARIABLE="[^"]*"/VARIABLE="123456789"/' file_to_modify
Or, more generally:
sed -r 's/VARIABLE="[^"]*"/VARIABLE="'"$1"'"/' file_to_modify
Both of the above use a regular expression that looks for 'VARIABLE="anything-at-all"' and replaces it with, in the first example above 'VARIABLE="123456789"' or, in the second, 'VARIABLE="$1"' where "$1" is the first argument to your script. The key element is [^"]. It means any character other than double-quote. [^"]* means any number of characters other than double-quote. Thus, we replace whatever was in the double-quotes before, "[^"]*", with our new value "123456789" or, in the second case, "$1".
The second case is a bit tricky. We want to substitute $1 into the expression but the expression is itself in single quotes. Inside single-quotes, bash will not substitute for $1. So, the sed command is broken up into three parts:
# spaces added for exposition but don't try to use it this way
's/VARIABLE="[^"]*"/VARIABLE="' "$1" '"/'
The first part is in single quotes and bash passes it literally to sed. The second part is in double-quotes, so bash will subsitute in for the value of `$``. The third part is in single-quotes and gets passed to sed literally.
MORE: Here is a simple way to test this approach on the command line without depending on any files:
$ new=1234 ; echo 'VARIABLE="DEFAULT"' | sed -r 's/VARIABLE="[^"]*"/VARIABLE="'"$new"'"/'
VARIABLE="1234"
The first line above is the command run at the prompt ($). The second is the output from running the command..

printing the ampersand

I have a bash script that takes a url with variables and writes it to a file, problem is the ampersand is interfering and being interpreted as a command / control character.
In this situation the string cannot be escaped BEFORE being passed to the script and I have yet to find any way to do this.
if [ $1 ] ; then
url=$1
printf %q "$url" > "/somepath/somefile"
fi
with $1 being for example localhost?x=1&y=2&z=3
What get's printed is only the part before the first ampersand: "localhost?x=1"
I have also tried echo instead of printf but it's exactly the same ??
Your script is fine, but you need to invoke the script with a quoted parameter:
./myscript.sh "localhost?x=1&y=2&z=3"
There is no problem with echo nor print. The problem is that when you run the script, it starts those 2 jobs in background. For more information you can check: http://hacktux.com/bash/ampersand.
You can simply start script with 'localhost?x=1&y=2&z=3' in apostrophes, so bash will not treat ampersand as operator but just as normal character.
Quote things. Replace all $1s with "$1"s. And quote argument when you actually invoke your script.

How to echo a variable containing an unescaped dollar sign in bash

If I have a variable containing an unescaped dollar sign, is there any way I can echo the entire contents of the variable?
For example something calls a script:
./script.sh "test1$test2"
and then if I want to use the parameter it gets "truncated" like so:
echo ${1}
test1
Of course single-quoting the varaible name doesn't help. I can't figure out how to quote it so that I can at least escape the dollar sign myself once the script recieves the parameter.
The problem is that script receives "test1" in the first place and it cannot possibly know that there was a reference to an empty (undeclared) variable. You have to escape the $ before passing it to the script, like this:
./script.sh "test1\$test2"
Or use single quotes ' like this:
./script.sh 'test1$test2'
In which case bash will not expand variables from that parameter string.
The variable is replaced before the script is run.
./script.sh 'test1$test2'
by using single quotes , meta characters like $ will retain its literal value. If double quotes are used, variable names will get interpolated.
As Ignacio told you, the variable is replaced, so your scripts gets ./script.sh test1 as values for $0 and $1.
But even in the case you had used literal quotes to pass the argument, you shoudl always quote "$1" in your echo "${1}". This is a good practice.

Resources