i wrote a shell script as you can see followed. The script reads all line which in .dat file and writes screen matching words according to specified parameter but if/else block doesn’t properly.Both block if and else fired same time.
sh file
#!/bin/bash p="*.dat" k="$1" for f in $p do if [ "$k" == "$f" ]; then echo "$f present" else echo "not found $k" fi cat $f done
dat file
lorem ipsum loremium dolor sit amet ipso
terminal
$ ./loc.sh lor
result
not found lor lorem ipsum loremium dolor sit amet ipso
Advertisement
Answer
The original code didn’t ever look inside of a file until after running the comparison — it merely compared the name of each .dat
file to the target, and allowed only exact matches (not substrings).
Consider instead:
while read -r line; do if [[ $line = *"$1"* ]]; then echo "$1 present in $line" else echo "$1 not found in $line" fi done < <(cat *.dat)
- Using
cat *.dat
combines all the files into a single stream. Enclosing this in<(cat *.dat)
generates a filename which can read from to yield that stream; using< <(cat *.dat)
redirects stdin from this file (within the scope of thewhile
loop for which this redirection takes place). - Using
while read
processes an input stream line-by-line (see BashFAQ #1). - Using a test of
[[ $line = *"$1"* ]]
allows the target (contents of$1
) to be found inside a line, instead of only matching when$1
matches the entire line as a whole. You can also have this effect with[[ $line =~ "$1" ]]
. Note that the quotes are mandatory for correct operation in either of these cases. Using a
for
loop to iterate over lines is extremely poor practice; see Don’t Read Lines With For. If you want to use afor
loop, use it to iterate over files instead:for f in *.dat; do # handle case where no files exist [[ -e "$f" ]] || continue # read each given file while read -r line; do if [[ $line = *"$1"* ]]; then echo "$1 present in $line in file $f" else echo "$1 not present in $line in file $f" fi done <"$f" done