Inserting newline between matched text is overwriting - perl

I have a text file. I am trying to search for a comma followed by a date, like ",08/18/2014".
It looks like my code finds it, but it replaces it with a comma and a new line and removes everything after it.
if ($firstline =~ s|\,(\d{2}\/.*)|\,\n|g){
print "$firstline";
How do I add a new line between the comma and the date and not remove my text and date?
Thanks.

You can reference your capture groups in your replace expression. I also expanded the regular expression to match the date exactly:
if ($firstline =~ s|,(\d{2}-\d{2}-\d{4})|,\n$1|g) {
print "$firstline\n";
}

Using look ahead/behind:
s|(?<=,)(?=\d{2}\/)|\n|g
or
s|,\K(?=\d{2}\/)|\n|g # Probably faster, but requires 5.10+

Similar to Hunter's answer, without the extended regex, like so:
(Oh, and I don't think you need the backslash before the comma):
$firstline = "hello world ,10/20/1987, sounds great to me"; # testing...
if ($firstline =~ s|,(\d{2}/)|,\n$1|g){
print "$firstline";
}
output:
hello world ,
10/20/1987, sounds great to me

Related

How to trim the last part of string using Perl?

I need to trim the last part of the string here. The string i have is : abc|bcd|cde|.
I need to get rid of the last |... The trim() command is not helping for some reason may be i am using it wrong, please help... thank you.
This can be done with a simple substitution.
my $string = "abc|bcd|cde|";
$string =~ s/\|$//;
Use chop:
my $string = "abc|bcd|cde|";
chop($string);
say $string;
output:
abc|bcd|cde
From the doc:
Chops off the last character of a string and returns the character
chopped. It is much more efficient than s/.$//s because it neither
scans nor copies the string. If VARIABLE is omitted, chops $_ . If
VARIABLE is a hash, it chops the hash's values, but not its keys.

Why does split not return anything?

I am trying to get that Perl split working for more than 2 hours. I don't see an error. Maybe some other eyes can look at it and see the issue. I am sure its a silly one:
#versionsplit=split('.',"15.0.3");
print $versionsplit[0];
print $versionsplit[1];
print $versionsplit[2];
I just get an empty array. Any idea why?
You need:
#versionsplit=split(/\./,"15.0.3");
The first argument to split is a regular expression, not a string. And . is the regex symbol which means ‘match any character’. So all the characters in your input string were being treated as separators, and split wasn't finding anything between them to return.
the "." represents any character.You need to escape it for split function to recognise as a field separator.
change your line to
#versionsplit=split('\.',"15.0.3");

how to delete single quotes but not apostrophes in perl

I would like to know how to delete single quotes but not apostrophes in perl.
For example:
'It's raining again!'
print
It's raining again!
Thanks so much
If you assume that a single-quote is always preceded or followed by whitespace, the following pair of regular expressions should work:
$line =~ s/\s'/ /g; #preceded by whitespace
$line =~ s/'\s/ /g; #followed by whitespace
you also need to account for if the string starts or ends with a single quote:
$str =~ s/^'//; #at the start of a string
$str =~ s/'$//; #at the end of a string
foreach (<DATA>) {
s/(:?(^\s*'|'$))//g;
print;
}
__DATA__
'It's raining again!'
OUTPUT
It's raining again!
EXPLANATIONS
there's more one than one way to do it
(:?) prevent non-needed capture
Tricky one. Some single quotes come after or before letters, but you want to remove only those between letters. Perhaps something like this, using negative lookarounds:
s/(?<![\pL\s])'|'(?![\pL\s])//g;
Which will remove either single quotes without letters or whitespace after or before it. Lots of negations to keep track of there. The expanded version:
s/
(?<![\pL\s])' # no letters or whitespace before single quote
| # or
'(?![\pL\s]) # no letters or whitespace after single quote
//gx;
This will cover words like - as Eli Algranti pointed out in a comment - boys' toys and that's, but language is always tricky to predict. For example, it will be next to impossible to solve something like:
'She looked at him and said, 'That's impossible!''
Of course, if you expect your single quotes to appear only at end or beginning of string, you don't need to be this fancy, you can just remove the last and first character, with any means necessary. Such as, for example, as sputnik just suggested:
s/^'|'$//g;

Best way to print fixed columns table in Perl (using underscores instead of spaces)

I need to format database records into a table that a web forum can display properly (using bbcode). The forum in question does not respect spaces no matter which type of formatting tag I use but does have a monospace font, so I need to replace all spaces by underscores like this to keep everything aligned:
Field____Field____Field
Value____Value____Value
Value____Value____Value
Value____Value____Value
Value____Value____Value
I've looked into Perl formats and printf, but I can't figure out how to make the spaces and tabs into underscore using these methods. The text also have variable length, so I need the columns to be variable as well (can't hardcode fixed values).
Any help would be appreciated. Thanks!
A bit of a hack but I would use sprintf but I would replace the space in my values with another character that can not be found in these values (like ~). This can be done with a simple regex.
After sprintf I would replace the spaces with underlines and my special character in the values back to space.
You don't need anything advanced, you just need to replace the spaces with underscore:
my $str = "Field Field Field";
$str =~ tr/ /_/;
print $str;
In case the values in your fields may contain tabs (or other space-like characters) you may want to do the following:
my $str = "Field Field\tContinued Field";
$str =~ s/\s/_/g;
print $str;

Removing quotes from string

So I thought this would just be a simple issue however I'm getting the incorrect results. Basically I am trying to remove the quotes around a string. For example I have the string "01:00" and I want 01:00, below is the code on how I thought I would be able to do this:
$expected_start_time = $conditions =~ m/(\"[^\"])/;
Every time this runs it returns 1, so I'm guessing that it is just returning true and not actually extracting the string from the quotes. This happen no matter what is in the quotes "02:00", "02:20", "08:00", etc.
All you forgot was parens for the LHS to put the match into list context so it returns the submatch group(s). The normal way to do this is:
($expected_start_time) = $condition =~ /"([^"]*)"/;
It appears that you know that the first and last character are quotes. If that is the case, use
$expected_start_time = substr $conditions, 1, -1;
No need for a regexp.
The brute force way is:
$expected_start_time = $conditions;
$expected_start_time =~ s/"//g;
Note that the original regex:
m/(\"[^\"])/
would capture the opening quote and the following non-quote character. To capture the non-quote characters between double quotes, you'd need some variant on:
m/"([^"]*)"/;
This being Perl (and regexes), TMTOWTDI - There's More Than One Way Do It.
In scalar context a regex returns true if the regex matches the string. You can access the match with $1. See perlre.