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
Related
Consider a string
Message="Hello WoRld"
I would like to substitute the upper case R by the lower case r
echo "$Message" > file.txt
NewMessage=$(sed 's/R/r/' file.txt)
works fine! The following would work as well
NewMessage=$(echo ${Message} | sed 's/R/r/')
But my first reflex was to use command substitution
NewMessage=$(sed 's/R/r/' <("$Message"))
but it does not work. Why doesn't it work?
your cmd-sub version was missing the leading M?
But you want
NewMessage=$(sed 's/R/r/' <(echo "$Message"))
OR your shell may support
NewMessage=$(sed 's/R/r/' <<< "$Message")
edit
and the simplest, most widely supported solution would be much simpler
NewMessage=$(echo "$Message" | sed 's/R/r/')
If you need absolute stone-age compatibility to Bourne Shell (true /bin/sh) then you'll have to forego the nice $(..cmdSub) syntax and use back-quotes for command-substitution:
NewMessage=`echo "$Message" | sed 's/R/r/'`
IHTH
If you are using bash 4, you don't need sed:
NewMessage=${Message,,R}
Can someone please help with this because I can't seem to find a solution. I have the following script that works fine:
#!/bin/bash
#Checks the number of lines in the userdomains file
NUM=`awk 'END {print NR}' /etc/userdomains.hristian`;
echo $NUM
#Prints out a particular line from the file (should work with $NUM eventually)
USER=`sed -n 4p /etc/userdomains.hristian`
echo $USER
#Edits the output so that only the username is left
USER2=`echo $USER | awk '{print $NF}'`
echo $USER2
However, when I substitute the 4 on line 12 with the variable $NUM, like this, it doesn't work:
USER=`sed -n $NUMp /etc/userdomains.hristian`
I tried a number of different combinations of quotes and ${}, however none of them seem to work because I'm a BASH newbie. Help please :)
I'm not sure exactly what you've already tried but this works for me:
$ cat out
line 1
line 2
line 3
line 4
line 5
$ num=4
$ a=`sed -n ${num}p out`
$ echo "$a"
line 4
To be clear, the issue here is that you need to separate the expansion of $num from the p in the sed command. That's what the curly braces do.
Note that I'm using lowercase variable names. Uppercase ones should be be reserved for use by the shell. I would also recommend using the more modern $() syntax for command substitution:
a=$(sed -n "${num}p" out)
The double quotes around the sed command aren't necessary but they don't do any harm. In general, it's a good idea to use them around expansions.
Presumably the script in your question is a learning exercise, which is why you have done all of the steps separately. For the record, you could do the whole thing in one go like this:
awk 'END { print $NF }' /etc/userdomains.hristian
In the END block, the values from the last line in the file can still be accessed, so you can print the last field directly.
Your trying to evaluate the variable $NUMp rather than $NUM. Try this instead:
USER=`sed -n ${NUM}p /etc/userdomains.hristian`
I have been trying to truncate a filename, both at start and end.
I could achieve this with the following code:
#!bin/bash
FILENAME="hello123.txt"
NAME=${FILENAME%.t*}
NUMBER=${NAME:5}
DOESNTWORK=${${FILENAME%.t*}:5}
echo "$FILENAME"
echo "$NAME"
echo "$NUMBER"
echo "$DOESNTWORK"
My issue is with the DOESNTWORK line.
I get this error for the line: main.sh: line 7: ${"${FILENAME%.t*}":5}: bad substitution
Can someone please point out the mistake in the line?
Thanks,
If you can use GNU grep why not use below:
DOESNTWORK=$(grep -o -E '[[:digit:]]+' <<< "$FILENAME")
Or with sed:
DOESNTWORK=$(sed 's/[^0-9]*//g' <<< "$FILENAME")
There are (at least) two ways to accomplish this in bash, at least for your specifically cited example. The first removes all characters that are not digits:
echo "${FILENAME//[^0-9]/}"
The second is by requesting a specific substring, which you were already partially using:
echo "${FILENAME:5:3}"
Which if these is most useful to you depends on how your actual use case compares to the example you cited...
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
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