Weird behavior when concatenate string in bash shell [duplicate] - bash

This question already has answers here:
Bash script prints "Command Not Found" on empty lines
(17 answers)
Closed 6 years ago.
I have a file store version information and I wrote a shell to read two fields and combine them. But when I concatenate those two fields, it show me a werid result.
version file:
buildVer = 3
version = 1.0.0
script looks like:
#!bin/bash
verFile='version'
sdk_ver=`cat $verFile | sed -nE 's/version = (.*)/\1/p'`
build_ver=`cat $verFile | sed -nE 's/buildVer = (.*)/\1/p'`
echo $sdk_ver
echo $build_ver
tagname="$sdk_ver.$build_ver"
echo $tagname
The output shows
1.0.0
3
.30.0
I tried to echo the sdk_ver directly without read it from file, this piece of script works well. So I think it may relate to the sed, but I couldn't figure out how to fix it.
Does anyone know why it acts like that?

You're getting this problem because of presence of DOS line ending i.e. \r in each line of version file.
Use dos2unix or this sed command to remove \r first:
sed -i 's/\r//' version
btw you can also simplify your script using pure BASH constructs like this:
#!/bin/bash
while IFS='= ' read -r k v; do
declare $k="$v"
done < <(sed $'s/\r//' version)
tagname="$version.$buildVer"
echo "$tagname"
This will give output:
1.0.0.3

Alternate solution, with awk:
awk '/version/{v=$3} /buildVer/{b=$3} END{print v "." b}' version.txt
Example:
$ cat file.txt
buildVer = 3
version = 1.0.0
$ awk '/version/{v=$3} /buildVer/{b=$3} END{print v "." b}' file.txt
1.0.0.3

Related

Add a new line of text at the top of a file in bash shell [duplicate]

This question already has answers here:
Unix command to prepend text to a file
(21 answers)
Closed 4 years ago.
I want to write a bash script that takes my file:
READ_ME.MD
two
three
four
and makes it
READ_ME.MD
one
two
three
four
There are a bunch of similar StackOverflow questions, but I tried their answers and haven't been successful.
These are the bash scripts that I have tried and failed with:
test.sh
sed '1s/^/one/' READ_ME.md > READ_ME.md
Result: Clears the contents of my file
test.sh
sed '1,1s/^/insert this /' READ_ME.md > READ_ME.md
Result: Clears the contents of my file
test.sh
sed -i '1s/^/one\n/' READ_ME.md
Result: sed: 1: "READ_ME.md": invalid command code R
Any help would be appreciated.
You can use this BSD sed command:
sed -i '' '1i\
one
' file
-i will save changes inline to file.
If you want to add a line at the top if same line is not already there then use BSD sed command:
line='one'
sed -i '' '1{/'"$line"'/!i\
'"$line"'
}' file
Your last example works for me with GNU sed. Based on the error message you added, I'd guess you're working on a Mac system? According to this blog post, a suffix argument may be required on Mac versions of sed:
sed -i ' ' '1s/^one\n/' READ_ME.md
If this is bash or zsh, you can use process substitution like so.
% cat x
one
two
three
% cat <(echo "zero") x
zero
one
two
three
Redirect this into a temp file and copy it back to the original
there is always ed
printf '%s\n' H 1i "one" . w | ed -s READ_ME.MD

Shell command to delete \n on 1 out of 2 line on a file [duplicate]

This question already has answers here:
How to merge every two lines into one from the command line?
(21 answers)
Closed 6 years ago.
I'm looking for a shell command to delete the return chariot on one line out of two.
I have a file like this :
1.32640997
;;P
1.14517534
;;P
1.16120958
;;P
...
And I would like something like this:
1.32640997;;P
1.14517534;;P
1.16120958;;P
...
Is it possible?
Thanks
Using GNU paste
paste -d '' - - < file
Using BSD paste
paste -d '\0' - - < file
paste produces two columns from stdin with - - as parameters, 3 columns with - - - as parameters, and so on.
-d is to specify a column separator, use '\0' for no separator.
Using Perl
perl -ne 'chomp($prev = $_); print $prev, scalar <>' < file
Using awk
$ awk '{printf "%s%s",$0,(NR%2==0?ORS:"")}' File
1.32640997;;P
1.14517534;;P
1.16120958;;P
This prints each line followed by nothing for odd lines or followed by the output record separator for even lines.
Using sed
This works by reading in lines in pairs:
$ sed 'N; s/\n//' File
1.32640997;;P
1.14517534;;P
1.16120958;;P
N reads in the next line and s/\n// removes the newline.
Using xargs:
xargs -n 2 -d '\n' printf '%s%s\n' <file

Unix Shell Script: Remove common prefix from a variable [duplicate]

This question already has answers here:
Remove a fixed prefix/suffix from a string in Bash
(9 answers)
Closed 2 years ago.
I have 2 variables one which is holding the prefix and other one the complete string.
For e.g
prefix="TEST_"
Str="TEST_FILENAME.xls"
I want the the Str to be compared against prefix and remove that common characters 'TEST_' and i want the output as FILENAME.xls. Please advise if it can be done with minimal lines of coding. Thanks a lot.
Using BASH you can do:
prefix="TEST_"
str="TEST_FILENAME.xls"
echo "${str#$prefix}"
FILENAME.xls
If not using BASH you can use sed:
sed "s/^$prefix//" <<< "$str"
FILENAME.xls
Try this:
$ Str=$(echo $Str | sed "s/^${prefix}//")
$ echo $Str
FILENAME.xls
Or using awk:
$ echo $Str | awk -F $prefix '{print $2}'
FILENAME.xls

Print specific lines of a file in Terminal [duplicate]

This question already has answers here:
How can I extract a predetermined range of lines from a text file on Unix?
(28 answers)
Closed 7 years ago.
This seems pretty silly, but I haven't found a tool that does this, so I figured I'd ask just to make sure one doesn't exist before trying to code it up myself:
Is there any easy way to cat or less specific lines of a file?
I'm hoping for behavior like this:
# -s == start && -f == finish
# we want to print lines 5 - 10 of file.txt
cat -s 5 -f 10 file.txt
Even something a little simpler would be appreciated, but I just don't know of any tool that does this:
# print from line 10 to the end of the file
cat -s 10 file.txt
I'm thinking that both of these functionalities could be easily created with a mixture of head, tail, and wc -l, but maybe there are builtins that do this of which I'm unaware?
yes awk and sed can help
for lines 5 to 10
awk 'NR>4&&NR<11' file.txt
sed -n '5,10p' file.txt
for lines 10 to last line
awk 'NR>9' file.txt
sed -n '10,$p' file.txt

Shell script to parse through a file ( csv ) and process line by line [duplicate]

This question already has answers here:
Bash: Parse CSV with quotes, commas and newlines
(10 answers)
Closed 2 years ago.
Hi Need a shell script to parse through the csv file - Line by line and then field by field ]
the file will look like this
X1,X2,X3,X4
Y1,Y2,Y3,Y4
I need to extract each of these X1,X2....
I wrote a script but it fails if the line exceeds one line..
Here's how I would do it.
First i set the IFS environment variable to tell read that "," is the field separator.
export IFS=","
Given the file "input" containing the data you provided, I can use the following code:
cat test | while read a b c d; do echo "$a:$b:$c:$d"; done
To quickly recap what is going on above. cat test | reads the file and pipes it to while. while runs the code between do and done while read returns true. read reads a line from standard input and separates it into variables ("a", "b", "c" and "d") according to the value of $IFS. Finally echo just displays the variables we read.
Which gives me the following output
X1:X2:X3:X4
Y1:Y2:Y3:Y4
BTW, the BASH manual is always good reading. You'll learn something new every time you read it.
Since eykanal mentioned AWk and and sed, I thought I'd show how you could use them.
awk -F, 'BEGIN{OFS="\n"}{$1=$1; print}' inputfile
or
sed 's/,/\n/' inputfile
Then a shell script could process their output:
awk_or_sed_cmd | while read -r field
do
do_something "$field"
done
Of course, you could do the processing within the AWK script:
awk -F, '{for (i=1;i<=NF;i++) do_something($i)}' inputfile
ls -l
vi filename.sh
#!bin/sh
echo "INPUT PATTERN"
cat > test
(input data and save it)
cat test | while read (input);(ex : "$a:$b:$c:$d");
done
echo "pattern shown as "$a:$b:$c:$d"\n"
exit(0;);

Resources