Bash printing "\r" - bash

I'm using OS X, and there is no "-e" equivalent.
How can I textually print "\r"?
Is there even a way to do that?

You could use echo $'\r' which is supported by bash

How about:
echo "\\r"
Works for me.

printf '\r'
The printf command in general tends to be better than echo for cases other than very simple ones. It has more capabilities and fewer variations from one implementation to another.

Script:
#!/bin/bash
r=$'\r'
t=$'\t'
echo "${t}${t}1${r}${t}2${r}3"
Output:
3 2 1

Related

Trying to retrieve first 5 characters from string in bash error?

I'm trying to retrieve the first 5 characters from a string and but keep getting a Bad substitution error for the string manipulation line, I have the following lines in my teststring.sh script:
TESTSTRINGONE="MOTEST"
NEWTESTSTRING=${TESTSTRINGONE:0:5}
echo ${NEWTESTSTRING}
I have went over the syntax many times and cant see what im doing wrong
Thanks
Depending on your shell, you may be able to use the following syntax:
expr substr $string $position $length
So for your example:
TESTSTRINGONE="MOTEST"
echo `expr substr ${TESTSTRINGONE} 0 5`
Alternatively,
echo 'MOTEST' | cut -c1-5
or
echo 'MOTEST' | awk '{print substr($0,0,5)}'
echo 'mystring' |cut -c1-5 is an alternative solution to ur problem.
more on unix cut program
Works here:
$ TESTSTRINGONE="MOTEST"
$ NEWTESTSTRING=${TESTSTRINGONE:0:5}
$ echo ${NEWTESTSTRING}
MOTES
What shell are you using?
Substrings with ${variablename:0:5} are a bash feature, not available in basic shells. Are you sure you're running this under bash? Check the shebang line (at the beginning of the script), and make sure it's #!/bin/bash, not #!/bin/sh. And make sure you don't run it with the sh command (i.e. sh scriptname), since that overrides the shebang.
This might work for you:
printf "%.5s" $TESTSTRINGONE
Works in most shells
TESTSTRINGONE="MOTEST"
NEWTESTSTRING=${TESTSTRINGONE%"${TESTSTRINGONE#?????}"}
echo ${NEWTESTSTRING}
# MOTES
echo $TESTSTRINGONE|awk '{print substr($0,0,5)}'
You were so close! Here is the easiest solution: NEWTESTSTRING=$(echo ${TESTSTRINGONE::5})
So for your example:
$ TESTSTRINGONE="MOTEST"
$ NEWTESTSTRING=$(echo ${TESTSTRINGONE::5})
$ echo $NEWTESTSTRING
MOTES
You can try sed if you like -
[jaypal:~/Temp] TESTSTRINGONE="MOTEST"
[jaypal:~/Temp] sed 's/\(.\{5\}\).*/\1/' <<< "$TESTSTRINGONE"
MOTES
That parameter expansion should work (what version of bash do you have?)
Here's another approach:
read -n 5 NEWTESTSTRING <<< "$TESTSTRINGONE"
The original syntax will work with BASH but not with DASH. On debian systems you
might think you are using bash, but maybe dash instead. If /bin/dash/exist then
try temporarily renaming dash to something like no.dash, and then create soft a
link, aka ln -s /bin/bash /bin/dash and see if that fixes the problem.
expr substr $string $position $length
$position starts from 1

How to use the read command in Bash?

When I try to use the read command in Bash like this:
echo hello | read str
echo $str
Nothing echoed, while I think str should contain the string hello. Can anybody please help me understand this behavior?
The read in your script command is fine. However, you execute it in the pipeline, which means it is in a subshell, therefore, the variables it reads to are not visible in the parent shell. You can either
move the rest of the script in the subshell, too:
echo hello | { read str
echo $str
}
or use command substitution to get the value of the variable out of the subshell
str=$(echo hello)
echo $str
or a slightly more complicated example (Grabbing the 2nd element of ls)
str=$(ls | { read a; read a; echo $a; })
echo $str
Other bash alternatives that do not involve a subshell:
read str <<END # here-doc
hello
END
read str <<< "hello" # here-string
read str < <(echo hello) # process substitution
Typical usage might look like:
i=0
echo -e "hello1\nhello2\nhello3" | while read str ; do
echo "$((++i)): $str"
done
and output
1: hello1
2: hello2
3: hello3
The value disappears since the read command is run in a separate subshell: Bash FAQ 24
To put my two cents here: on KSH, reading as is to a variable will work, because according to the IBM AIX documentation, KSH's read does affects the current shell environment:
The setting of shell variables by the read command affects the current shell execution environment.
This just resulted in me spending a good few minutes figuring out why a one-liner ending with read that I've used a zillion times before on AIX didn't work on Linux... it's because KSH does saves to the current environment and BASH doesn't!
I really only use read with "while" and a do loop:
echo "This is NOT a test." | while read -r a b c theRest; do
echo "$a" "$b" "$theRest"; done
This is a test.
For what it's worth, I have seen the recommendation to always use -r with the read command in bash.
You don't need echo to use read
read -p "Guess a Number" NUMBER
Another alternative altogether is to use the printf function.
printf -v str 'hello'
Moreover, this construct, combined with the use of single quotes where appropriate, helps to avoid the multi-escape problems of subshells and other forms of interpolative quoting.
Do you need the pipe?
echo -ne "$MENU"
read NUMBER

I'm having trouble performing arithmetic expressions in UNIX

I have the following script:
#!/bin/sh
r=3
r=$((r+5))
echo r
However, I get this error:
Syntax error at line 3: $ unexpected.
I don't understand what I'm doing wrong. I'm following this online guide to the letter http://www.unixtutorial.org/2008/06/arithmetic-operations-in-unix-scripts/
This sounds fine if you're using bash, but $((r+5)) might not be supported if you're using another shell. What does /bin/sh point to? Have you considered replacing it with /bin/bash if it's available?
The shebang line is your problem. bash is not sh. Change it to #!/bin/bash and it will work. You'll also want echo $r instead of echo r.
It works for me (printing 8), if you change echo r to echo $r. What version of sh do you have installed? What unix distribution?
You might want to try the following:
#!/bin/sh
r=3
r=$((r + 5))
echo $r
For doing maths (including decimals/floats), you can use awkor bc/dc.
awk -vr="$r" 'BEGIN{r=r+5;print r}'
or
echo "$r+5" | bc

Variable value inconsistency on BASH and CSH

May God never give you the bane of working on Solaris.
Now, I am trying to run this simple shell script:
#!/bin/sh
input="a
b
c"
data="123"
while read eachline
do
data="$data$eachline"
done << EOF
$(echo "$input")
EOF
echo "$data"
exit 0
On RHEL(BASH) I receive output as expected i.e "123abc", however, on Solaris I receive just "123".
After fair bit of googling, I realized that Solaris is forking a process for code inside the while loop and hence the variable's($data) value is not reflected on the outside of while loop.
Any hope to make this code compatible on both platforms would be greatly appreciated.
And oh yes, using a temp file for redirection would not be a very elegant solution :| .
Do you have a bash executable on the Solaris box ? I note you're referring to bash on RHEL, but your shell is set to #!/bin/sh (i.e. the vanilla Bourne shell).
How about this (please note backticks):
#!/bin/sh
input="a
b
c"
data="123"
z=`while read eachline
do
data="$data$eachline"
done << EOF
$(echo "$input")
EOF
echo $data
`
echo $z
exit 0
Your script works fine on Mac OS X 10.5, which is certified Single Unix Specification version 3.
The behaviour of while in /bin/sh on Solaris is very strange. Can you provide the link where you found the forking issue?
A possible solution may be to use another shell, e.g., /bin/ksh.
Edit
The examples provided by your links don't show an issue with while but a normal behaviour of any shell. The basic construct of all of them is:
first_command | second_command_updating_variable
The fact that second_command_updating_variable is a while loop is not important. What is important is that the second command of the pipe is executed in a subshell and cannot modify variables of its parent shell.
This code below solved my problem. I guess the key here was to echo the variable from within the subshell and ofcourse, not use the "here" document.
I have tested this code on CSH/BASH/KSH.
#!/bin/sh
input="a
b
c"
printf "$input" | {
data="123"
while read eachline
do
data="$data$eachline"
done
echo "$data"
}
exit 0
My heartfelt thanks to all who participated in this discussion.
Why execute a subshell in the here document?
while read eachline
do
data="$data$eachline"
done << EOF
$(echo "$input")
EOF
You could just interpolate:
while read eachline
do
data="$data$eachline"
done << EOF
$input
EOF
Or echo:
echo "$input" | while read eachline
do
data="$data$eachline"
done
Actually, when I tested these, they all worked on Solaris just fine for me, so I'm not sure why you had trouble.

echo "-e" doesn't print anything

I'm using GNU bash, version 3.00.15(1)-release (x86_64-redhat-linux-gnu). And this command:
echo "-e"
doesn't print anything. I guess this is because "-e" is one of a valid options of echo command because echo "-n" and echo "-E" (the other two options) also produce empty strings.
The question is how to escape the sequence "-e" for echo to get the natural output ("-e").
The one true way to print any arbitrary string:
printf "%s" "$vars"
This is a tough one ;)
Usually you would use double dashes to tell the command that it should stop interpreting options, but echo will only output those:
$ echo -- -e
-- -e
You can use -e itself to get around the problem:
$ echo -e '\055e'
-e
Also, as others have pointed out, if you don't insist on using the bash builtin echo, your /bin/echo binary might be the GNU version of the tool (check the man page) and thus understand the POSIXLY_CORRECT environment variable:
$ POSIXLY_CORRECT=1 /bin/echo -e
-e
There may be a better way, but this works:
printf -- "-e\n"
You could cheat by doing
echo "-e "
That would be dash, e, space.
Alternatively you can use the more complex, but more precise:
echo -e \\\\x2De
[root#scintia mail]# POSIXLY_CORRECT=1; export POSIXLY_CORRECT
[root#scintia mail]# /bin/echo "-e"
-e
[root#scintia mail]#
Another alternative:
echo x-e | sed 's/^x//'
This is the way recommended by the autoconf manual:
[...] It is often possible to avoid this problem using 'echo "x$word"', taking the 'x' into account later in the pipe.
After paying careful attention to the man page :)
SYSV3=1 /usr/bin/echo -e
works, on Solaris at least
I like that one using a herestring:
cat <<<"-e"
Another way:
echo -e' '
echo -e " \b-e"
/bin/echo -e
works, but why?
[resin#nevada ~]$ which echo
/bin/echo

Resources