ksh: Replacing a word with asterisks causes bad substitution error - ksh

I'm trying replace a specific word read from a file with asterisks of the same length.
Eg;
cat -> ***
snake -> *****
So, in my script below, it works in bash but not in ksh
for next in `cat $filename`; do
rep=${next//[^\"]/*}
echo "$next replace with $rep"
done;
Running it in ksh gives me a bad substitution error, Any ideas?
Thanks

In older versions of ksh, you'll have to use the sed command:
for next in `cat $filename`; do
rep=$(print $next | sed 's/[^\"]/*/g')
echo "$next replace with $rep"
done;

You can use tr:
rep=$(printf "%s" "$next" | tr -c '"' '*')

Related

how to use index number from loop to SED [duplicate]

I have abc.sh:
exec $ROOT/Subsystem/xyz.sh
On a Unix box, if I print echo $HOME then I get /HOME/COM/FILE.
I want to replace $ROOT with $HOME using sed.
Expected Output:
exec /HOME/COM/FILE/Subsystem/xyz.sh
I tried, but I'm not getting the expected output:
sed 's/$ROOT/"${HOME}"/g' abc.sh > abc.sh.1
Addition:
If I have abc.sh
exec $ROOT/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
then with
sed "s|\$INSTALLROOT/|${INSTALLROOT}|" abc.sh
it is only replacing first $ROOT, i.e., output is coming as
exec /HOME/COM/FILE/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
Say:
sed "s|\$ROOT|${HOME}|" abc.sh
Note:
Use double quotes so that the shell would expand variables.
Use a separator different than / since the replacement contains /
Escape the $ in the pattern since you don't want to expand it.
EDIT: In order to replace all occurrences of $ROOT, say
sed "s|\$ROOT|${HOME}|g" abc.sh
This might work for you:
sed 's|$ROOT|'"${HOME}"'|g' abc.sh > abc.sh.1
This may also can help
input="inputtext"
output="outputtext"
sed "s/$input/${output}/" inputfile > outputfile
The safe for a special chars workaround from https://www.baeldung.com/linux/sed-substitution-variables with improvement for \ char:
#!/bin/bash
to="/foo\\bar#baz"
echo "str %FROM% str" | sed "s#%FROM%#$(echo ${to//\\/\\\\} | sed 's/#/\\#/g')#g"

sed or grep to read between a set of parentheses

I'm trying to read a version number from between a set of parentheses, from this output of some command:
Test Application version 1.3.5
card 0: A version 0x1010000 (1.0.0), 20 ch
Total known cards: 1
What I'm looking to get is 1.0.0.
I've tried variations of sed and grep:
command.sh | grep -o -P '(?<="(").*(?=")")'
command.sh | sed -e 's/(\(.*\))/\1/'
and plenty of variations. No luck :-(
Help?
You were almost there! In pgrep, use backslashes to keep literal meaning of parentheses, not double quotes:
grep -o -P '(?<=\().*(?=\))'
Having GNU grep you can also use the \K escape sequence available in perl mode:
grep -oP '\(\K[^)]+'
\K removes what has been matched so far. In this case the starting ( gets removed from match.
Alternatively you could use awk:
awk -F'[()]' 'NF>1{print $2}'
The command splits input lines using parentheses as delimiters. Once a line has been splitted into multiple fields (meaning the parentheses were found) the version number is the second field and gets printed.
Btw, the sed command you've shown should be:
sed -ne 's/.*(\(.*\)).*/\1/p'
There are a couple of variations that will work. First with grep and sed:
grep '(' filename | sed 's/^.*[(]\(.*\)[)].*$/\1/'
or with a short shell script:
#!/bin/sh
while read -r line; do
value=$(expr "$line" : ".*(\(.*\)).*")
if [ "x$value" != "x" ]; then
printf "%s\n" "$value"
fi
done <"$1"
Both return 1.0.0 for your given input file.

Using variables as parameter in sed [duplicate]

I have abc.sh:
exec $ROOT/Subsystem/xyz.sh
On a Unix box, if I print echo $HOME then I get /HOME/COM/FILE.
I want to replace $ROOT with $HOME using sed.
Expected Output:
exec /HOME/COM/FILE/Subsystem/xyz.sh
I tried, but I'm not getting the expected output:
sed 's/$ROOT/"${HOME}"/g' abc.sh > abc.sh.1
Addition:
If I have abc.sh
exec $ROOT/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
then with
sed "s|\$INSTALLROOT/|${INSTALLROOT}|" abc.sh
it is only replacing first $ROOT, i.e., output is coming as
exec /HOME/COM/FILE/Subsystem/xyz.sh $ROOT/ystem/xyz1.sh
Say:
sed "s|\$ROOT|${HOME}|" abc.sh
Note:
Use double quotes so that the shell would expand variables.
Use a separator different than / since the replacement contains /
Escape the $ in the pattern since you don't want to expand it.
EDIT: In order to replace all occurrences of $ROOT, say
sed "s|\$ROOT|${HOME}|g" abc.sh
This might work for you:
sed 's|$ROOT|'"${HOME}"'|g' abc.sh > abc.sh.1
This may also can help
input="inputtext"
output="outputtext"
sed "s/$input/${output}/" inputfile > outputfile
The safe for a special chars workaround from https://www.baeldung.com/linux/sed-substitution-variables with improvement for \ char:
#!/bin/bash
to="/foo\\bar#baz"
echo "str %FROM% str" | sed "s#%FROM%#$(echo ${to//\\/\\\\} | sed 's/#/\\#/g')#g"

String substitute in Shell script

I suppose to strip down a substring in my shell script. I am trying as follows:
fileName="Test_VSS_TT.csv.old"
here i want to remove the string ".csv.old" and my
test=${fileName%.*}
but getting bad substitution error.
you are looking for test=${filename%%.*}
the doc for parameter expansion in bash here and in zsh here
%.* will match the first .* pattern, whereas %%.* will match the longest one
[edit]
if sed is available, you could try something like that : echo "filename.txt.bin" | sed "s/\..*//g" which yields filename
Here you go,
$ echo $f
Test_VSS_TT.csv.old
$ test=${f%%.*}
$ echo $test
Test_VSS_TT
%% will do a longest match. So it matches from the first dot upto the last and then removes the matched characters.
If your intention is to extract file name without extension, then how about this?
$ echo ${fileName}
Test_VSS_TT.csv.old
$ test=`echo ${fileName} |cut -d '.' -f1`
$ echo $test
Test_VSS_TT
echo "Test_VSS_TT.csv.old"| awk -F"." '{print $1}'

How to extract and chop version string from file in bash

I have a simple text file ./version containing a version number. Unfortunately, sometimes the version number in the file is followed by whitespaces and newlines like
1.1.3[space][space][newline]
[newline]
[newline]
What is the best, easiest and shortest way to extract the version number into a bash variable without the trailing spaces and newlines? I tried
var=`cat ./version | tr -d ' '`
which works for the whitespaces but when appending a tr -d '\n' it does not work.
Thanks,
Chris
$ echo -e "1.1.1 \n\n" > ./version
$ read var < ./version
$ echo -n "$var" | od -a
0000000 1 . 1 . 1
0000005
Pure Bash, no other process:
echo -e "1.2.3 \n\n" > .version
version=$(<.version)
version=${version// /}
echo "'$version'"
result: '1.2.3'
I still do not know why, but after deleting and recreating the version file this worked:
var=`cat ./version | tr -d ' ' | tr -d '\n'`
I'm confused... what can you do different when creating a text file. However, it works now.
I like the pure bash version from fgm's answer.
I provide this one-line perl command to remove also other characters if any:
perl -pe '($_)=/([0-9]+([.][0-9]+)+)/'
The extracted version number is trimmed/stripped (no newline or carriage return symbols):
$> V=$( bash --version | perl -pe '($_)=/([0-9]+([.][0-9]+)+)/' )
$> echo "The bash version is '$V'"
The bash version is '4.2.45'
I provide more explanation and give other more sophisticated (but still short) one-line perl commands in my other answer.

Resources