How to check if a line from a file is empty with bash - 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:]]/}" ]

Related

Finding presence of substring within a string in BASH

I have a script that is trying to find the presence of a given string inside a file of arbitrary text.
I've settled on something like:
#!/bin/bash
file="myfile.txt"
for j in `cat blacklist.txt`; do
echo Searching for $j...
unset match
match=`grep -i -m1 -o "$j" $file`
if [ $match ]; then
echo "Match: $match"
fi
done
Blacklist.txt contains lines of potential matches, like so:
matchthis
"match this too"
thisisasingleword
"This is multiple words"
myfile.txt could be something like:
I would matchthis if I could match things with grep. I really wish I could.
When I ask it to match this too, it fails to matchthis. It should match this too - right?
If I run this at a bash prompt, like so:
j="match this too"
grep -i -m1 -o "$j" myfile.txt
...I get "match this too".
However, when the batch file runs, despite the variables being set correctly (verified via echo lines), it never greps properly and returns nothing.
Where am I going wrong?
Wouldn't
grep -owF -f blacklist.txt myfile.txt
instead of writing an inefficient loop, do what you want?
Would you please try:
#!/bin/bash
file="myfile.txt"
while IFS= read -r j; do
j=${j#\"}; j=${j%\"} # remove surrounding double quotes
echo "Searching for $j..."
match=$(grep -i -m1 -o "$j" "$file")
if (( $? == 0 )); then # if match
echo "Match: $match" # then print it
fi
done < blacklist.txt
Output:
Searching for matchthis...
Match: matchthis
Searching for match this too...
Match: match this too
match this too
Searching for thisisasingleword...
Searching for This is multiple words...
I wound up abandoning grep entirely and using sed instead.
match=`sed -n "s/.*\($j\).*/\1/p" $file
Works well, and I was able to use unquoted multiple word phrases in the blacklist file.
With this:
if [ $match ]; then
you are passing random arguments to test. This is not how you properly check for variable net being empty. Use test -n:
if [ -n "$match" ]; then
You might also use grep's exit code instead:
if [ "$?" -eq 0 ]; then
for ... in X splits X at spaces by default, and you are expecting the script to match whole lines.
Define IFS properly:
IFS='
'
for j in `cat blacklist.txt`; do
blacklist.txt contains "match this too" with quotes, and it is read like this by for loop and matched literally.
j="match this too" does not cause j variable to contain quotes.
j='"match this too"' does, and then it will not match.
Since whole lines are read properly from the blacklist.txt file now, you can probably remove quotes from that file.
Script:
#!/bin/bash
file="myfile.txt"
IFS='
'
for j in `cat blacklist.txt`; do
echo Searching for $j...
unset match
match=`grep -i -m1 -o "$j" "$file"`
if [ -n "$match" ]; then
echo "Match: $match"
fi
done
Alternative to the for ... in ... loop (no IFS= needed):
while read; do
j="$REPLY"
...
done < 'blacklist.txt'

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

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.

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: read line and keep spaces

I am trying to read lines from a file containing multiple lines. I want to identify lines that contain only spaces.
By definition, an empty line is empty and does not contain anything (including spaces).
I want to detect lines that seems to be empty but they are not (lines that contain spaces only)
while read line; do
if [[ `echo "$line" | wc -w` == 0 && `echo "$line" | wc -c` > 1 ]];
then
echo "Fake empty line detected"
fi
done < "$1"
But because read ignores spaces in the start and in the end of a string my code isn't working.
an example of a file
hi
hi
(empty line, no spaces or any other char)
hi
(two spaces)
hey
Please help me to fix the code
Disable word splitting by clearing the value of IFS (the internal field separator):
while IFS= read -r line; do
....
done < "$1"
The -r isn't strictly necessary, but it is good practice.
Also, a simpler way to check the value of line (I assume you're looking for a line with nothing but whitespace):
if [[ $line =~ ^$ ]]; then
echo "Fake empty line detected"
fi
Following your code, it can be improved.
while read line; do
if [ -z "$line" ]
then
echo "Fake empty line detected"
fi
done < "$1"
The test -z checks if $line is empty.
Output:
Fake empty line detected
Fake empty line detected

Resources