0

Hi I am new to programming.

While trying to execute the script below, with an input file of this form (in this case they are called nohd*.txt files)

NSGEAPKNFGLDVKITGESENDRDLGTAPGGTLNDIG
IIIIMMMMMOOOOOOOOOOOOOMMMMMMMMMMMIIII

I want to count the columns that have text from file d.txt, see next.

D
O

to do this I wrote the following script

#!/bin/bash
for z in {1..141}
do
        a=0
        l=$(tail -1 nohd$z.txt | wc -m)
        x=$(cat d.txt)
                for ((p; p<=l; p++))
                do
                        if [ "$(cut -c $p nohd$z.txt)" = "$x" ] ; then
                                a=$((a+1))
                                p=$((p+1))
                        fi
                done
        echo $a
done

I'm running this script using ./script it shows this error:

cut: invalid byte/character position ‘{1..351}’

it turns correctly only the first value, for the rest of values it turns 0 the expected output is in the following form

5
20
4

Please, can anyone help me with this? Thank u

14
  • 1
    Hi and welcome to the site! Could you please edit your question and show us what output you expect here? Your script is taking a very complicated approach and has some mistakes so it is hard to understand what you are trying to do with it.
    – terdon
    Commented Oct 14, 2019 at 16:52
  • 2
    Yes, how? sh script.sh? ./script.sh? bash script.sh? Something else? Please edit your question and clarify. Also, please show your expected output as I requested before.
    – terdon
    Commented Oct 14, 2019 at 17:14
  • 1
    Please edit your question to add your expected output and show us how you run your script. Comments are hard to read, easy to miss and can be deleted without warning.
    – terdon
    Commented Oct 14, 2019 at 17:27
  • 1
    Why would you have 3 lines of output if you only look for 2 letters? Please show us the output you expect from the example input you gave. We need this to understand what you are trying to do.
    – terdon
    Commented Oct 14, 2019 at 17:33
  • 1
    The value of p should be 1 for the first comparison with cut, so try to change your loop to for ((p=1; p<l; p++)) and you probably don't need to increment p with p=$((p+1)) (remove it).
    – Freddy
    Commented Oct 14, 2019 at 17:43

1 Answer 1

1
#!/usr/bin/perl

use File::Slurp;

# read d.txt and turn into a regular expression.
my $re = '^(' . join ('|',read_file('./d.txt', chomp => 1)) . ')$';

# read input files and print location of matches.
while (<>) {
  for (my $i=0;$i <= length; $i++) {
    printf "%s\n", $i+1 if (substr($_,$i,1) =~ m/$re/o);
  }
}

This perl script prints the positions of every `D' and 'O' character in the input lines.

Save as, e.g. islem.pl, make it executable with chmod +x islem.pl, and run it like this:

$ ./islem.pl nohd*.txt
12
22
24
35
10
11
12
13
14
15
16
17
18
19
20
21
22

The above output is from saving your sample data as nohd1.txt.


I think I misread your question. It looks like you want the count of matches on a line, not the position of every match. If that's what you wanted, try this instead:

#!/usr/bin/perl -l

use File::Slurp;

# read d.txt and turn into a regular expression.
my $re = '^(' . join ('|',read_file('./d.txt', chomp => 1)) . ')$';

# read input files and print location of matches.
while (<>) {
  my $count=0;
  for (my $i=0;$i <= length; $i++) {
    $count++ if (substr($_,$i,1) =~ m/$re/o);
  };
  print $count;
}

Sample output:

$ ./islem2.pl nohd*
4
13

This is easily adapted to many variations. For example, if if you wanted to print the filename and line number along with the corresponding count in : delimited format:

#!/usr/bin/perl -l

use File::Slurp;

# read d.txt and turn into a regular expression.
my $re = '^(' . join ('|',read_file('./d.txt', chomp => 1)) . ')$';

# read input files and print location of matches.
while (<>) {
  my $count=0;
  for (my $i=0;$i <= length; $i++) {
    $count++ if (substr($_,$i,1) =~ m/$re/o);
  };
  print "$ARGV:$.:$count";
} continue {
  # explicitly close the current file on eof to reset the line counter
  # after each input file because perl only has a cumulative line
  # counter ($.) rather than both FR and FNR like awk.
  close ARGV if eof;
}

Sample output:

$ ./islem3.pl nohd*.txt
nohd1.txt:1:4
nohd1.txt:2:13

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .