Print with space [duplicate] - bash

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 1 year ago.
How to save a line with spaces without line breaks in a file?
Such as this:
Value2="Server=server1.windows.net,1433;Database=DB;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;"
using:
printf '%s\n' $Value2 >> "./print.csv"
At present it gets saved as:
Server=server1.windows.net,1433;Database=DB;Persist
Security
Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection
Timeout=30;

The variable $Value2 isn't quoted, and has two separate spaces, so the printf command sees three strings, not one -- so printf prints three strings on three lines. To make printf see just one string, put the variable in quotes, like this:
printf '%s\n' "${Value2}"
Output:
Server=server1.windows.net,1433;Database=DB;Persist Security Info=False;MultipleActiveResultSets=False;Encrypt=True;TrustServerCertificate=False;Connection Timeout=30;
Or, as proof use wc to count the lines:
printf '%s\n' "${Value2}" | wc -l
Output:
1

Related

How to write to a file with escape characters in bash [duplicate]

This question already has answers here:
Echo newline in Bash prints literal \n
(22 answers)
Closed 1 year ago.
A very simple question. I'd like to write several lines to a file with just one line containing multiple \n. I.e. my input string would be hello\nhello\nhello, I'd like to write it to a file hello.txt, and when cat hello.txt it should give me
hello
hello
hello
However, when I do echo "hello\nhello\nhello" > hello.txt, it just gave me the literal string, without converting \n to a newline.
I wonder how to write such a line to a file.
You want either echo -e or, generally even better printf
printf 'Hello %s\n\nWelcome to my %s document\nmultiline document\n\n\n\nEnd\n' \
"John" "yellow" > "/some/path/hello.txt";

How to insert dynamic matching pattern in bash? [duplicate]

This question already has answers here:
Difference between single and double quotes in Bash
(7 answers)
Closed 3 years ago.
I was looking at this link Check if a Bash array contains a value which says how to check for existence of an item in a list as follows:
if printf '%s\n' ${myarray[#]} | grep -q -P '^mypattern$'; then
# ...
fi
However, I want mypattern value to be passed as a variable as follows:
mynewpattern="xyz"
then I was expecting the following to work
if printf '%s\n' ${myarray[#]} | grep -q -P '^"$mynewpattern"$'; then
# ...
fi
But it is not picking the new pattern of xyz. What is the appropriate syntax to insert the new pattern?
I have just started learning bash.
The single quotes are wrong; you want double quotes instead of single.
However, grep -P is also slightly wrong here; it's not properly portable, and your pattern doesn't use any of the syntax which -P enables; also, you should quote your array properly.
if printf '%s\n' "${myarray[#]}" |
grep -q "^$mypattern\$"
then
...
Text between single quotes is passed through verbatim. If you want the shell to perform variable interpolation, use double quotes (and then you need to escape any literal backslash, dollar sign, or backtick).
Could you please try using like grep -q -P "^$var$"(in your script)
Here is an example script for same scenario for an Input_file(since no samples for array elements were provided so explaining it with an sample/example script here).
##Shell variable
var="bla"
##A sample Input_file
cat << EOF > Input_file
blabla test test
123abcd123test
bla
EOF
##Following is the code to check.
if grep -q -P "^$var$" Input_file
then
echo "match found."
fi
Above will only match lines which are starting with variable val's value.

why is [ for i in ${ARR[#]}; do echo ${i} ] printing space-delimited output? [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 5 years ago.
I have read input from file using:
declare -a ARR
readarray -t ARR < <(cat /etc/passwd | tr "\n" "\n" )
This prints it fine, but I want to access each line:
printf '%s\n' "${ARR[#]}
This is splitting the input on spaces:
for i in ${ARR[#]}; do
echo ${i}
done
Does echo requires a particular option to print it correctly?
Based on this answer, changing it to echo "${i}" should fix it, but it doesn't.
This has the same problem:
printf "${i} \n"
To avoid splitting on spaces, replace:
for i in ${ARR[#]}; do
With:
for i in "${ARR[#]}"; do
Without the double-quotes, the shell does word-splitting.
It would also be best to replace echo ${i} with echo "${i}". Without the double-quotes the ${i} will be subject to word-splitting (which will cause multiple spaces to be collapsed to one blank) and pathname expansion (which may cause words with shell-active characters to be replaced with filenames from the current directory).

How to understand quoting variables deeply [duplicate]

This question already has answers here:
When to wrap quotes around a shell variable?
(5 answers)
Closed 6 years ago.
I test the following bash file test.sh. But how to explain the output. Sometimes I would remember quoting string variables means preserving whitespace in a single variable, but how to understand it instead of remembering it.
list="one two three"
for a in $list
do
echo "$a"
done
for a in "$list"
do
echo "$a"
done
output:
one
two
three
one two three
Continuing from the comment and explanation of word-splitting and the Internal Field Separator, here is a short example that should help:
#!/bin/bash
list="one two three"
printf "\nDefault IFS (space, tab, newline):\n\n"
for a in $list
do
echo "$a"
done
for a in "$list"
do
echo "$a"
done
printf "\nIFS breaking only on newline:\n\n"
IFS=$'\n'
for a in $list
do
echo "$a"
done
for a in "$list"
do
echo "$a"
done
(if you continue in a script and don't exit after setting IFS to a new value and need to restore the current (or default) IFS, either save the current (e.g. curifs="$IFS" and restore when done with your block, IFS="$curifs") or just reset to the default (e.g. IFS=$' \t\n'). you can also, just run your block with the new IFS in a subshell, e.g. (IFS=$',\n'; #do stuff), or in a while block, e.g. while IFS=$'\n' read -r line; do ... )
Example Use/Output
$ bash ifs.sh
Default IFS (space, tab, newline):
one
two
three
one two three
IFS breaking only on newline:
one two three
one two three

linux shell script: split string, put them in an array then loop through them [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Split string based on delimiter in Bash?
In a bash script how do I split string with a separator like ; and loop through the resulting array?
You can probably skip the step of explicitly creating an array...
One trick that I like to use is to set the inter-field separator (IFS) to the delimiter character. This is especially handy for iterating through the space or return delimited results from the stdout of any of a number of unix commands.
Below is an example using semicolons (as you had mentioned in your question):
export IFS=";"
sentence="one;two;three"
for word in $sentence; do
echo "$word"
done
Note: in regular Bourne-shell scripting setting and exporting the IFS would occur on two separate lines (IFS='x'; export IFS;).
If you don't wish to mess with IFS (perhaps for the code within the loop) this might help.
If know that your string will not have whitespace, you can substitute the ';' with a space and use the for/in construct:
#local str
for str in ${STR//;/ } ; do
echo "+ \"$str\""
done
But if you might have whitespace, then for this approach you will need to use a temp variable to hold the "rest" like this:
#local str rest
rest=$STR
while [ -n "$rest" ] ; do
str=${rest%%;*} # Everything up to the first ';'
# Trim up to the first ';' -- and handle final case, too.
[ "$rest" = "${rest/;/}" ] && rest= || rest=${rest#*;}
echo "+ \"$str\""
done
Here's a variation on ashirazi's answer which doesn't rely on $IFS. It does have its own issues which I ouline below.
sentence="one;two;three"
sentence=${sentence//;/$'\n'} # change the semicolons to white space
for word in $sentence
do
echo "$word"
done
Here I've used a newline, but you could use a tab "\t" or a space. However, if any of those characters are in the text it will be split there, too. That's the advantage of $IFS - it can not only enable a separator, but disable the default ones. Just make sure you save its value before you change it - as others have suggested.
Here is an example code that you may use:
$ STR="String;1;2;3"
$ for EACH in `echo "$STR" | grep -o -e "[^;]*"`; do
echo "Found: \"$EACH\"";
done
grep -o -e "[^;]*" will select anything that is not ';', therefore spliting the string by ';'.
Hope that help.
sentence="one;two;three"
a="${sentence};"
while [ -n "${a}" ]
do
echo ${a%%;*}
a=${a#*;}
done

Resources