I have a text file that has 60 character positions. I want to be able to search for a value/word entered by the user in positions 05-12. How do I go about doing this without using awk, pearl, etc?

For example the text file is

commA6314   ifosfamide               30     12 

home5341209 urokinase    6314               37

And if someone inputs 6314, then it would output the line

commA6314   ifosfamide               30     12

I was thinking of using grep, but not too sure. Any help?

  • 5
    why "without using awk"? it's an obvious choice for data that's structured into fields such as this – steeldriver Mar 1 '17 at 22:49
  • That's the challenge my prof gave us, but I have no clue going about this other than using awk – JVAN Mar 1 '17 at 22:50
  • Also I'm not clear what you mean by "columns" in this context: your example seems to show a match in the first (whitespace delimited) column - not between columns 05-12. Or are you referring to character positions? – steeldriver Mar 1 '17 at 22:58
  • character positions, sorry – JVAN Mar 1 '17 at 22:59
  • I think it might be fairly easy with grep, at least my quick test seemed to work fine. (it is on purpose I'm not yet saying how I did it.) – Doug Smythies Mar 1 '17 at 23:06

You could use

grep -E "^.{4}.?.?.?.?.?.?.?$pattern" 

where $pattern is the user input, I mean in something like

$ echo "enter a pattern: "; read pattern; grep -E "^.{4}.?.?.?.?.?.?.?$pattern" file
enter a pattern: 
commA6314   ifosfamide               30     12 

^.{4}.?.?.?.?.?.?.? that's the first 4 characters locked, then the next 7 characters are optional, meaning if the pattern is only one character and it's in the 12th position, it would be found, and if it's 7 characters and starts from the 5th position, it would still be found.

  • ^ start of line
  • . any character
  • {4} four of the preceding character
  • ? zero or one of the preceding character

Bash allows extracting sub-strings of specific variable. All you have to do is read file line by line within while IFS= read -r structure:

while IFS= read -r line;
    if [[ ${line:5:12} =~ "$1" ]];
        echo "$line"
done < "$2"

Note the syntax: in ${var:5:12} 5 is starting position and 12 is offset, so in this case it searches from char position 5 till 17. If you need to calculate off-set based on user's input, you can use bash arithmetic to determine off-set like end=$((12-5)) and use that variable within substring expression like ${var:5:$end}

Test run:

$ ./search_substrings.sh "6314" input.txt                                                                                
commA6314   ifosfamide               30     12  

Note that this avoids use of external tools like grep which adheres to requirements, although keep in mind this is not a very practical solution, and in real world you'd rather use Perl or awk

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.