Searching multiple strings [closed] - string

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
How can i search from set of strings
i would like a perl script to search for either "aaa", "bbb", "ccc", "ddd"
Searching from txt file
Example 1
some random text
blah
blah
blah
//Car/trunk/sandbox/users/Tom/xyz/bbb/toyota
Desired Output:
//Car/trunk/sandbox/users/Tom/xyz/...
Example 2
some random text
blah
blah
blah
//Car/trunk/sandbox/users/Alex/abc/defg/ddd/honda/accord
Desired Output:
//Car/trunk/sandbox/users/Alex/abc/defg/...
Basically searching from the given set of strings from "aaa", "bbb", "ccc", "ddd" it finds "bbb" in example 1 and takes everything before and adds back slash with "..."
Please note that it is reading from one text file, example 1 is a example of text file and same goes for example 2.
So far this is what i have.
my $infile = 'new5.txt';
my #strings = qw/aaa bbb ccc ddd/;
local #ARGV = ($infile);
while( <> ){
print;
}

The code you have so far is what I would call a hackish way to cat a file.
First of all, we will get the obligatory pragmas out of the way:
use strict;
use warnings;
use autodie;
The last one makes sure the script dies if a file was not found or could not be opened.
You initialized $infile and #strings correctly, good.
The proper or more accepted way to open and loop over the contents of a file is this:
open(my $FILE, "<", $infile);
while(my $line = <$FILE>) {
chomp $line;
...
}
close($FILE);
Within this loop you want to try to match each element of the #strings array. That can be accomplished by looping over each element in the array:
foreach my $elem (#strings) {
...
}
In this loop you want to do the match. If it does, print out what you need (and go the next line in the file). Look up the perlre man page to see what the stuff after =~ is doing:
if ($line =~ m#/$elem/#) {
print SOMETHING;
next;
}
What would that SOMETHING be? According to the perlvar man page, `$`` (among other mnemonics) is the variable that contains the string before the matched string:
print $`."/...\n";
Put it all together and you have your script.

Related

How to sort a specific date-time column in bash [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 6 months ago.
Improve this question
I want to sort a specific column on a file by time. The type is the following: 2022-08-25_TIME_HERE.
Date its "fixed", only the time needs sorting by time.
So for example we have the following part from the file (fifth column on file):
2022-08-25_22:55:01
2022-08-25_20:23:24
2022-08-25_22:53:07
2022-08-25_21:53:30
2022-08-25_20:23:33
2022-08-25_20:22:14
What I want after sorting:
2022-08-25_20:22:14
2022-08-25_20:23:24
2022-08-25_20:23:33
2022-08-25_21:53:30
2022-08-25_22:53:07
2022-08-25_22:55:01
I have tried a lot of commands such as awk, perl, sed but I am not getting the desired result. The difficulty is in the fixed part of the column.
Any ideas?
perl works just fine:
#!/usr/bin/env perl
#
# Sort timestamps
use 5.12.10;
use Time::Piece;
my $fmt='%Y-%m-%d_%H:%M:%S';
my #t;
while( <DATA> ){
if( $_ !~ m#\d{4}-\d{1,2}-\d{1,2}_\d{1,2}:\d{2}:\d{2}# ){
say STDERR "Invalid format $_";
next
}
chop; # Delete newline
push #t, Time::Piece->strptime($_, $fmt);
}
say $_->strftime($fmt) foreach sort #t;
__DATA__
2022-08-25_22:55:01
2022-08-25_20:23:24
2022-08-25_22:53:07
2022-08-25_21:53:30
2022-08-25_20:23:33
2022-08-25_20:22:14
To put that in a one-liner, you could do:
perl -MTime::Piece -lnE 'eval { push #t, Time::Piece->strptime($_,"'$fmt'") } or say "Invalid input: $_" } { say $_->strftime("'$fmt'") foreach sort #t' input-file

How do I list the line number of a file with a Perl script? [duplicate]

This question already has answers here:
How to get the current line number of a file opened using Perl
(3 answers)
Closed 3 years ago.
I've made a Perl script to list the contents of a specified file, but I also want to see the line number of the file content. What functions in Perl enable this?
This is my code:
#!/usr/local/bin/perl
use warnings;
use strict;
print "Specify the file you want to look at:\n";
my $file_name = <STDIN>;
chomp $file_name;
open(FH, '<', $file_name) or die "Cannot open $file_name: $!";
print "This is the listed content of: $file_name\n";
while(<FH>){
print $_;
}
close(FH);
This is what happens when I run the script, and this is what I would like it to do.
Actual result Wished result
Hello 1. Hello
my 2. my
name 3. name
is 4. is
Janne 5. Janne
You can do something like this:
my $line_n = 1;
while(<FH>){
print "$line_n. $_";
$line_n++;
}

Reading a text file in Perl, Searching for a Word, Returning Line Number [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 8 years ago.
Improve this question
I'm trying to write a piece of code that is called by some C code with the data file and a specific word being passed in as an argument, and the line number being outputted to stdout. I played around with $substr some but that didn't work out.
I think it will ultimately be something like:
if ($oneLineofTheData !~ theSearchWord){
counter++;
}
else{
output counter to stdout
}
Would this be the easier way to handle this? How would I pass in the filename and search word? I'm very new to Perl so thank you in advance for helping out.
Thanks,
To pass arguments to a Perl program, use the #ARGV array.
To check for a presence of a substring in a string, use index.
$. keeps the line number of the last accessed filehandle.
#!/usr/bin/perl
use warnings;
use strict;
my ($filename, $word) = #ARGV;
open my $FH, '<', $filename or die $!;
while (my $line = <$FH>) {
if (-1 != index $line, $word) {
print $.;
exit
}
}
Put this in a file called whatever.pl:
$ct=0;
while(<>) {
if ($_ =~ m/$ARGV[0]/) {
print $ct;
exit;
}
$ct++;
}
Then on the command line run :
perl whatever.pl filename.txt wordToMatch

Why can't I print a very long string? [closed]

Closed. This question is not reproducible or was caused by typos. It is not currently accepting answers.
This question was caused by a typo or a problem that can no longer be reproduced. While similar questions may be on-topic here, this one was resolved in a way less likely to help future readers.
Closed 8 years ago.
Improve this question
I'm writing a Perl script that searches a kml file and I need to print a very long line of latitude/longitude coordinates. The following script successfully finds the string I'm looking for, but just prints a blank line instead of the value of the string:
#!/usr/bin/perl
# Strips unsupported tags out of a QGIS-generated kml and writes a new one
$file = $ARGV[0];
# read existing kml file
open( INFO, $file ); # Open the file
#lines = <INFO>; # Read it into an array
close(INFO); # Close the file
#print #lines; # Print the array
$x = 0;
$coord_string = "<coordinates>";
# go through each line looking for above string
foreach $line (#lines) {
$x++;
if ( $x > 12 ) {
if ( $line =~ $coord_string ) {
$thisCooordString = $line;
$var_startX = $x;
print "Found coord string: $thisCoordString\n";
print " on line: $var_startX\n";
}
}
}
The file that it's reading is here
and this is the output I get:
-bash-4.3$ perl writekml.pl HUC8short.kml
Found coord string:
on line: 25
Found coord string:
on line: 38
Is there some cap on the maximum length that a string can be in Perl? The longest line in this file is ~151,000 characters long. I've verified that all the lines in the file are read successfully.
You've misspelled the variable name (two os vs three os):
$thisCooordString = $line;
...
print "Found coord string: $thisCoordString\n";
Add use strict and use warnings to your script to prevent these sorts of errors.
Always include use strict and use warnings in EVERY perl script.
If you had done this, you would've gotten the following error message to clue you into your bug:
Global symbol "$thisCoordString" requires explicit package name
Adding these pragmas and simplifying your code results in the following:
#!/usr/bin/env perl
# Strips unsupported tags out of a QGIS-generated kml and writes a new one
use strict;
use warnings;
local #ARGV = 'HUC8short.kml';
while (<>) {
if ( $. > 12 && /<coordinates>/ ) {
print "Found coord string: $_\n";
print " on line: $.\n";
}
}
You can even try with perl one liners as shown below:
Perl One liner on windows command prompt:
perl -lne "if($_ =~ /<coordinates>/is && $. > 12) { print \"Found coord string : $_ \n"; print \" on line : $. \n\";}" HUC8short.kml
Perl One liner on unix prompt:
perl -lne 'if($_ =~ /<coordinates>/is && $. > 12) { print "Found coord string : $_ \n"; print " on line : $. \n";}' HUC8short.kml
As others have pointed out, you need. No, you MUST always use use strict; and use warnings;.
If you used strict, you would have gotten an error message telling you that your variable $thisCoordString or $thisCooordString was not declared with my. Using warnings would have warned you that you're printing an undefined string.
Your whole program is written in a very old (and obsolete) Perl programming style. This is the type of program writing I would have done back in Perl 3.0 days about two decades ago. Perl has changed quite a bit since then, and using the newer syntax will allow you to write easier to read and maintain programs.
Here's your basic program written in a more modern syntax:
#! /usr/bin/env perl
#
use strict; # Lets you know when you misspell variable names
use warnings; # Warns of issues (using undefined variables
use feature qw(say); # Let's you use 'say' instead of 'print' (No \n needed)
use autodie; # Program automatically dies on bad file operations
use IO::File; # Lots of nice file activity.
# Make Constants constant
use constant {
COORD_STRING => qr/<coordinates>/, # qr is a regular expression quoted string
};
my $file = shift;
# read existing kml file
open my $fh, '<', $file; # Three part open with scalar filehandle
while ( my $line = <$fh> ) {
chomp $line; # Always "chomp" on read
next unless $line =~ COORD_STRING; #Skip non-coord lines
say "Found coord string: $line";
say " on line: " . $fh->input_line_number;
}
close $fh;
Many Perl developers are self taught. There is nothing wrong with that, but many people learn Perl from looking at other people's obsolete code, or from reading old Perl manuals, or from developers who learned Perl from someone else back in the 1990s.
So, get some books on Modern Perl and learn the new syntax. You might also want to learn about things like references which can lead you to learn Object Oriented Perl. References and OO Perl will allow you to write longer and more complex programs.

CSV Bash loop Issue with Variables

I have a csv file which im trying to loop through with the purpose to find out if an User Input is found inside the csv data. I wrote the following code which sometimes works and others doesn't. It always stops working when I try to compare to a 2+ digit number. It works OK for numbers 1 through 9, but once u enter lets say 56 , or 99 or 100, it stops working.
the csv data is comma delimited, i have about 300 lines they are just like this.
1,John Doe,Calculus I,5.0
1,John Doe,Calculus II,4.3
1,John Doe,Physics II,3.5
2,Mary Poppins,Calculus I,3.7
2,Mary Poppins,Calculus II,4.7
2,Mary Poppins,Physics I,3.7
Data is just like that, all the way down until ID #100 for a total of 300 lines. Both the sh file and csv file are in the same folder, I'm using a fresh installation of Ubuntu 12.04.3, using gedit as the text editor.
I tried Echoing the variables ID and inside the IF conditionals but it doesn't behave the way it should when testing for the same value. Could someone point me out in the right direction. Thanks
Here's the code:
#s!/bin/bash
echo "enter your user ID";
read user;
INPUT_FILE=notas.csv
while IFS="," read r- ID name asignature final;
do
if [$ID = $user]; then
userType=1;
else
userType=2;
fi
done < notas.csv
Well, your code as written has a few issues.
You have r- instead of -r on the read line - I assume that's a typo not present in your actual code or you wouldn't get very far.
Similarly, you need space around the [...] brackets: [$ID is a syntax error.
You need to quote the parameter expansions in your if clause, and/or switch bracket types. You probably make it a numeric comparison as #imp25 suggested, which I would do by using ((...)).
You probably don't want to set userType to 2 in an else clause, because that will set it to 2 for everyone except whoever is listed last in the file (ID 100, presumably). You want to set it to 2 first, outside the loop. Then, inside the loop when you find a match, set it to 1 and break out of the loop:
userType=2
while IFS=, read -r ID name asignature final; do
if (( $ID == $user )); then
userType=1;
break
fi
done < notas.csv
You could also just use shell tools like awk:
userType=$(awk -F, -vtype=2 '($1=="'"$user"'") {type=1}; END {print type}' notas.csv)
or grep:
grep -q "^$user," notas.csv
userType=$(( $? + 1 ))
etc.
You should quote your variables in the if test statement. You should also perform a numeric test -eq rather than a string comparison =. So your if statement should look like:
if [[ "$ID" -eq "$user" ]]

Resources