How I change codes of a single txt file with a names list of csv in bash ubuntu? - bash

I have a single txt file where there are several codes with its metadata. However, I have been seeing how to change those codes with their names.
For this I have a list in csv with two columns, where the codes are in one and the names are in the other. These are 79.
This is a draft of script I have made:
#Here, the variable "Nombre" are the values of column 1 and the variable "Codigo" are the values of column 2 of nombres_codigos.csv file
#
#Then, I have use command sed to replace values of "Codigo" with values of "Nombre" into read RAxML_bipartitions_newick.newick file
#!/bin/bash
read nombres_codigos.csv
while read -r line || [[ -n $line ]]
do
Nombre="${line%;*}"
Codigo="${line#*;}"
echo "$Nombre"
echo "$Codigo"
read RAxML_bipartitions_newick.newick
while read -r line || [ -n "$line" ]
do
if [ "$Nombre" == "$Codigo" ]
then
sed -i "s/$Nombre/$Codigo/g" RAxML_bipartitions_newick.newick
echo "reemplazar"
else
echo "no reemplazar"
fi
done
p.s: nombres_codigos.csv is like:
Nombre;Codigo
EU528205_Floripondio_A56y7;EU528205_F
FJ710459_Floripondio_ABCD;FJ710459_F
EF514777_Floripondio123;EF514777_F
EU528999_Floripondio1;EU528999_F
...
My result is:
nombres.sh: line 2: read: `nombres_codigos.csv': not a valid identifier
nombres.sh: line 21: syntax error: unexpected end of file
But I hope from the file RAxML_bipartitions_newick.newick:
((((((EU528205_F:1.0000005000176948E-6,FJ710459_F:1.0000005000176948E-6):1.0000005000176948E-6,EF514777_F:1.0000005000176948E-...
switch to this:
((((((EU528205_Floripondio_A56y7:1.0000005000176948E-6,FJ710459_Floripondio_ABCD:1.0000005000176948E-6):1.0000005000176948E-6,EF514777_Floripondio123:1.0000005000176948E-...
Could someone help me modifying this, please? Thanks very much.

I am not 100% certain what you are attempting to accomplish, but it appears you want to read each line from nombres_codigos.csv and then split the line on the semi-colon. Then you want to check if the two parts are the same (which does not make sense with the sed expression that comes next)
A directly, albeit cleaned up reformatting would be:
#!/bin/bash
while read -r line || [ -n "$line" ]
do
Nombre="${line%;*}" ## separate using bash built-in parameter expansions
Codigo="${line#*;}"
echo "$Nombre"
echo "$Codigo"
if [ "$Nombre" == "$Codigo" ]
then
sed -i "s/$Nombre/$Codigo/g" RAxML_bipartitions_newick.newick
echo "reemplazar"
else
echo "no reemplazar"
fi
done < nombres_codigos.csv
If you separate "$Nombre" and "$Codigo" and then check if they are the SAME, then ... having sed replace "$Nombre" with "$Codigo" doesn't do anything at all. (It's like replacing 'A' with 'A') Did you mean:
if [ "$Nombre" != "$Codigo" ]
That would make what the script appears to do -- consistent. (e.g. change all instances of "$Nombre" with "$Codigo" in the file RAxML_bipartitions_newick.newick) If that is the case, then just change the conditional and let me know if you have further questions.

Related

Not able to skip blank lines in a shell script

I am reading a text file line by line and taking the count of all lines as a part of my requirement.
When there is blank line then it get messed up. I tried with if condition for [ -z "$line" ] , however not able to succeed.
Here is my current code:
countNumberOfCases() {
echo "2. Counting number of test cases -----------"
cd $SCRIPT_EXECUTION_DIR
FILE_NAME=Features
while read line || [[ -n "$line" ]]
do
TEST_CASE="$line"
if [ "${TEST_CASE:0:1}" != "#" ] ; then
cd $MVN_EXECUTION_DIR
runTestCase
fi
done < $FILE_NAME
echo " v_ToalNoOfCases : = " $v_ToalNoOfCases
}
And below is Features file
web/sprintTwo/TC_002_MultipleLoginScenario.feature
#web/sprintOne/TC_001_SendMoneyTransaction_Spec.feature
web/sprintTwo/TC_003_MultipleLoginScenario.feature
#web/sprintOne/TC_004_SendMoneyTransaction_Spec.feature
When there is blank line it wont work properly so my requirement is that if there is blank line then it should be skipped and should not get considered.
You can write your loop in a little more robust way:
#!/bin/bash
while read -r line || [[ $line ]]; do # read lines one by one
cd "$mvn_execution_dir" # make sure this is an absolute path
# or move it outside the loop unless "runTestCase" function changes the current directory
runTestCase "$line" # need to pass the argument?
done < <(sed -E '/^[[:blank:]]*$/d; /^[[:blank:]]+#/d' "$file_name") # strip blanks and comments
A few things:
get your script checked at shellcheck for common mistakes
see this post for proper variable naming convention:
Correct Bash and shell script variable capitalization
see this discussion about [ vs [[ in Bash
Test for non-zero length string in Bash: [ -n “$var” ] or [ “$var” ]
about reading lines from a text file
Looping through the content of a file in Bash

Compare strings in shell script

I have a file named parameters.txt whose contents are as follows:
sheet_name:TEST
sheet_id:CST
sheet_access:YES
And I have a shell script which fetches this text from the parameters.txt file. It uses : as a delimiter for each line of the parameters.txt file and stores whatever is left of : in var1 and whatever is right of : in var2. I want to print matched when var1 stores sheet_name and not matched when it doesn't stores sheet_name. Following is my code which always prints matched irrespective of what var1 stores:
filename=parameters.txt
IFS=$'\n' # make newlines the only separator
for j in `cat $filename`
do
var1=${j%:*} # stores text before :
var2=${j#*:} # stores text after :
if [ “$var1” == “sheet_name” ]; then
echo ‘matched’
else
echo “not matched“
fi
done
What am I doing wrong? Kindly help.
You have useless use of cat. But how about some [ shell parameter expansion ] ?
while read line
do
if [[ "${line%:*}" = "sheet_name" ]] #double quote variables deals word splitting
then
echo "matched"
fi
done<parameters.txt
would do exactly what you're looking for.
Message for you
[ ShellCheck ] says,
"To read lines rather than words, pipe/redirect to a 'while read'
loop."
Check [ this ] note from shellcheck.
How about this?
filename=parameters.txt
while IFS=: read -r first second; do
if [ “$first” == “sheet_name” ]; then
echo ‘matched’
else
echo “not matched“
fi
done < $filename

Bash command to see if a specific line of a file is empty

I'm trying to fix a bash script by adding in some error catching. I have a file (list.txt) that normally has content like this:
People found by location:
person: john [texas]
more info on john
Sometimes that file gets corrupted, and it only has that first line:
People found by location:
I'm trying to find a method to check that file to see if any data exists on line 2, and I want to include it in my bash script. Is this possible?
Simple and clean:
if test $(sed -n 2p < /path/to/file); then
# line 2 exists and it is not blank
else
# otherwise...
fi
With sed we extract the second line only. The test expression will evaluate to true only if there is a second non-blank line in the file.
I assume that you want to check whether line 2 of a given file contains any data or not.
[ "$(sed -n '2p' inputfile)" != "" ] && echo "Something present on line 2" || echo "Line 2 blank"
This would work even if the inputfile has just one line.
If you simply want to check whether the inputfile has one line or more, you can say:
[ "$(sed -n '$=' z)" == "1" ] && echo "Only one line" || echo "More than one line"
Sounds like you want to check if your file has more than 1 line
if (( $(wc -l < filename) > 1 )); then
echo I have a 2nd line
fi
Another approach which doesn't require external commands is:
if ( IFS=; read && read -r && [[ -n $REPLY ]]; ) < /path/to/file; then
echo true
else
echo false
fi

Parsing .csv file in bash, not reading final line

I'm trying to parse a csv file I made with Google Spreadsheet. It's very simple for testing purposes, and is basically:
1,2
3,4
5,6
The problem is that the csv doesn't end in a newline character so when I cat the file in BASH, I get
MacBook-Pro:Desktop kkSlider$ cat test.csv
1,2
3,4
5,6MacBook-Pro:Desktop kkSlider$
I just want to read line by line in a BASH script using a while loop that every guide suggests, and my script looks like this:
while IFS=',' read -r last first
do
echo "$last $first"
done < test.csv
The output is:
MacBook-Pro:Desktop kkSlider$ ./test.sh
1 2
3 4
Any ideas on how I could have it read that last line and echo it?
Thanks in advance.
You can force the input to your loop to end with a newline thus:
#!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
echo "$last $first"
done
Unfortunately, this may result in an empty line at the end of your output if the input already has a newline at the end. You can fix that with a little addition:
!/bin/bash
(cat test.csv ; echo) | while IFS=',' read -r last first
do
if [[ $last != "" ]] ; then
echo "$last $first"
fi
done
Another method relies on the fact that the values are being placed into the variables by the read but they're just not being output because of the while statement:
#!/bin/bash
while IFS=',' read -r last first
do
echo "$last $first"
done <test.csv
if [[ $last != "" ]] ; then
echo "$last $first"
fi
That one works without creating another subshell to modify the input to the while statement.
Of course, I'm assuming here that you want to do more inside the loop that just output the values with a space rather than a comma. If that's all you wanted to do, there are other tools better suited than a bash read loop, such as:
tr "," " " <test.csv
cat file |sed -e '${/^$/!s/$/\n/;}'| while IFS=',' read -r last first; do echo "$last $first"; done
If the last (unterminated) line needs to be processed differently from the rest, #paxdiablo's version with the extra if statement is the way to go; but if it's going to be handled like all the others, it's cleaner to process it in the main loop.
You can roll the "if there was an unterminated last line" into the main loop condition like this:
while IFS=',' read -r last first || [ -n "$last" ]
do
echo "$last $first"
done < test.csv

How to check if a line from a file is empty with bash

I have a while loop which reads lines from a file using read line.
Then I want to check if the line is empty or not, how can I do it?
I already found questions about lines with space or about a variable in this site.
You can use the test:
[ -z "$line" ]
From the bash man page:
-z string
True if the length of string is zero.
The -n operator checks if a string is not empty:
while read line
do
if [ -n "$line" ]
echo $line
fi
done < file.txt
If you'd want to exclude strings containing only whitespace, you could use bash's pattern replacement ${var//find/replacement}. For example:
if -n [ "${line//[[:space:]]/}" ]

Resources