How do you add flag in $() in bash [duplicate] - bash

This question already has answers here:
"echo -n" prints "-n"
(11 answers)
Closed 3 years ago.
I have the following bash script and seems the -n flag is always interpreted as string in echo
echo Hello, who am I talking to?
read login_name
login_name=$(echo -n $login_name | base64)
echo $login_name | base64 --decode
How do i correct that, or is there any other better syntax for my script?

Better use more portable printf instead of echo -n and use read -p with correct quoting;
read -p 'Hello, who am I talking to? ' login_name
login_name=$(printf '%s' "$login_name" | base64)
printf '%s' "$login_name" | base64 --decode
echo
PS: Just to clarify that there is nothing special about using any flag inside $(...) so one can use it like this:
dt=$(date -u '+%Y/%m/%d')
echo "$dt"

Related

Why do does echo $var have a different number of output characters than ${#var} expands to? [duplicate]

This question already has answers here:
Why wc adds plus one
(2 answers)
wc -c gives one more than I expected, why is that?
(3 answers)
Closed 5 months ago.
Hi I'm trying to learn bash scripting and I just want to get the character count of a variable. I tried to do it using these two different methods, but I can't understand why I get a difference of one character? Thanks for the help.
chars="ABCDEFGHIJKLMNOPQRSTUVWXYZ"
echo ${#chars}
echo $(echo "$chars" | wc -c)
26
27
Within parentheses you wrote
echo "$chars" | wc -c
You want
echo -n "$chars" | wc -c
The -n suppresses trailing newline.
As it stands, you are writing one additional character after
the 26 letters, and wc is faithfully counting it.
Try this to see the effect of the -n flag.
echo -n abc; echo -n def
echo uvw; echo xyz

How do I pipe into printf? [duplicate]

This question already has answers here:
Piping not working with echo command [duplicate]
(4 answers)
How to pass command output as multiple arguments to another command
(5 answers)
Closed 1 year ago.
I'm going nuts trying to understand what is the problem with this simple example (zsh or bash):
echo -n "6842" | printf "%'d"
The output is 0... why though? I'd like the output to be 6,842
Thanks in advance, I've had no luck for an hour now using google trying to figure this out...!
printf doesn't read arguments to format from standard input, but from the command line directly. For example, this works:
$ printf "%'d" 6842
6,842
You can convert output of a command to command-line arguments using command substitution:
$ printf "%'d" $(echo -n 6842)
6,842
If you want to invoke printf inside a pipeline, you can use xargs to read input and execute printf with the appropriate arguments:
echo -n "6842" | xargs printf "%'d"
printf does not format data passed to it on standard input; it takes a set of arguments, the first of which is the format, and the remainder are the values to display.
Luckily, this is exactly what xargs is for; to quote the manual:
xargs - build and execute command lines from standard input
So instead of piping to printf directly, you can pipe to xargs, and tell it to run printf for you with the given arguments. In short:
echo -n "6842" | xargs printf "%'d"

How to safely echo all arguments of a script? [duplicate]

This question already has answers here:
Bash: echo string that starts with "-"
(4 answers)
Closed 2 years ago.
I am writing a bash script that must echo all of its arguments, which is surprisingly difficult to do.
The naive implementation looks like this:
#!/bin/bash
echo "$#"
However, that fails with input such as:
> ./script.sh -n -e -v -e -r
-v -e -r>
How can I make this more robust, such that the above results in:
> ./script.sh -n -e -v -e -r
-n -e -v -e -r
>
echo command's behavior may be different between systems. The safest way is to use printf:
printf '%s\n' "$*"
According to posix:
It is not possible to use echo portably across all POSIX systems unless both -n (as the first argument) and escape sequences are omitted.
The printf utility can be used portably to emulate any of the traditional behaviors of the echo utility ...
Using printf instead of echo:
#!/bin/bash
printf "%s " "$#"
printf "\n"
You can use printf as well :
#!/bin/bash
printf "%s\n" "$*"
This one adds a space in the beginning but is rather simple :
#!/bin/bash
echo "" "$#"

Unable to pass password with space to shell script [duplicate]

This question already has answers here:
Passing arguments with spaces between (bash) script
(1 answer)
Parsing variables from config file in Bash
(7 answers)
Closed 5 years ago.
I have below script which turns on the tether mode on my intel edison.
But when I entered password with space it shows error that argument list is long. Without space it works perfectly fine
#!/usr/bin/env bash
SSID_FILE="/usr/share/apache2/htdocs/userhotspotname.conf"
if [ -s "$SSID_FILE" ]
then
filename="/usr/share/apache2/htdocs/userhotspotname.conf"
while IFS= read -r line; do
if [[ $line == hotspotna* ]] ; then
name=$(echo $line | grep "hotspotname" | cut -d= -f2)
fi
if [[ $line == hotspotpa* ]] ; then
pass=$(echo $line | grep "hotspotpass" | cut -d= -f2)
#pass="'${pass}'"
echo $pass
fi
done < "$filename"
**connmanctl tether wifi on "${name}" ${pass}**
fi
Below is userhotspotname.conf file content
hotspotname=cvg_space
hotspotpass=cgoma pwd space
Since password is with space
connmanctl tether wifi on "${name}" ${pass}
This command is failing since it is considering it as 4 arguments.
Please help in this if anyone has idea.

Propagate value of variable to outside of the loop [duplicate]

This question already has answers here:
A variable modified inside a while loop is not remembered
(8 answers)
Closed 4 years ago.
dpkg --list |grep linux-image |grep "ii " | while read line
do
arr=(${line})
let i=i+1
_constr+="${arr[2]} "
done
echo $i
echo ${_constr}
The echo statements outside of the loop do not display the expected variables.
How should I make the contents of the variable propagate outside the loop?
The problem is the pipe, not the loop. Try it this way
let i=0
arr=()
_constr=
while read -r line ; do
arr=("${line}")
let i=i+1
_constr+="${arr[2]} "
done < <(dpkg --list | grep linux-image | grep 'ii ')
echo "$i"
echo "${_constr}"
Pipes are executed in a subshell, as noted by Blagovest in his comment. Using process substitution instead (this is the < <(commands) syntax) keeps everything in the same process, so changes to global variables are possible.
Incidentally, your pipeline could be improved as well
dpkg --list | grep '^ii.*linux-image'
One less invocation of grep to worry about.
This somewhat by-passes your question (and it's a good question), but you can achieve the same results using simply:
_constr=($(dpkg --list | awk '/^ii.*linux-image/{print $2}'))
The ($(cmd)) construct initialises a bash array using the output of the command within.
[me#home]$ echo ${_constr[*]}
linux-image-2.6.35-22-generic linux-image-2.6.35-28-generic linux-image-generic
[me#home]$ echo ${_constr[2]}
linux-image-generic
and you can get the number of elements using ${#_constr[*]}.
[me#home]$ echo ${#_constr[*]}
3
Alternatively, you can move the echo statements inside the subshell:
dpkg --list |grep linux-image |grep "ii " | (
let i=0
declare -a arr
while read line
do
arr=(${line})
let i=i+1
_constr+="${arr[2]} "
done
echo $i
echo ${_constr}
)
Note the insertion of the parenthesis to explicitly define where the subshell begins and ends.

Resources