2

I have a problem with the grep command.

I have a file, called dictionary.txt, containing 2 columns of words, like

abc def
apple orange
hour minute

In my Bash script, having entered the word in the left column as an argument, I have to output the corresponding word on the right using the grep command.

A requirement is to use a loop.

I created this script:

#!/bin/bash

parola=$1

for traduzione in $( sort dictionary.txt )
do
     if [ $parola == $traduzione ]
     then
     grep $traduzione | cut -f 2 dictionary.txt
     fi
done

This does not work as described above.

Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
  • 1
    There are numerous _potential_ issues in your script (more than I can fit in a comment), but you haven’t told us what, _exactly_, you’re having trouble with, so it’s hard to answer. – Biffen May 06 '21 at 10:37
  • 2
    `grep | cut` is almost always better spelled `awk` – William Pursell May 06 '21 at 11:23
  • 1
    Tangentially, [don't read lines with `for`](http://mywiki.wooledge.org/DontReadLinesWithFor), and [quote your variables](https://stackoverflow.com/questions/10067266/when-to-wrap-quotes-around-a-shell-variable). – tripleee May 07 '21 at 10:30
  • The specific problem with `cut` is that it expects tab-delimited input, not space-delimited. – tripleee May 07 '21 at 10:31
  • 1
    Sorting the file seems completely superfluous here. – tripleee May 07 '21 at 10:33

2 Answers2

2

I'd suggest to replace the whole for loop with

awk -v word="$parola" '$1 == word{print $2;exit}' dictionary.txt

where

  • -v word="$parola" passes the parola variable to the awk script
  • $1 == word checks if the Column 1 value equals the parola
  • {print $2;exit} - prints the Column2 value and exits (remove exit if you need all matches on the further lines).

With dictionary.txt as

abc def
apple orange
hour minute

and script.sh as

#!/bin/bash
parola=$1
awk -v word="$parola" '$1 == word{print $2; exit}' dictionary.txt

the bash script.sh apple returns orange.

If you need a for loop you can use


#!/bin/bash
parola=$1

while IFS= read -a line; do
  read -r left right <<< "$line"
  if [ "$left" == "$parola" ]; then
     echo "$right";
  fi
done < dictionary.txt

That is:

  • Read dictionary.txt line by line assigning the current line value to the line variable
  • Read the values on a line into left and right variables
  • If left is equal to right, print right.
Wiktor Stribiżew
  • 607,720
  • 39
  • 448
  • 563
0

Why are you using a for-loop?

grep -w "word1" dictionary.txt

This shows you the line where you can find that word, so the for-loop is not even needed. For your information, -w means "only take whole words".

Dominique
  • 16,450
  • 15
  • 56
  • 112
  • I have to use the for because I have a specific request to use the for :-) – Alessio Scalzo May 06 '21 at 11:14
  • As mentioned in the answer, you accepted, there are two possibilities: either you use a `for`-loop, read line by line, and parse that line, or you use `grep` for finding the exact line you are looking for. It makes no sense (at least in this situation) to combine `for` and `grep`. – Dominique May 06 '21 at 12:39