Solved

How to change @ symbol of lines that are using the same @ symbol as the input record separator in Perl code?

Posted on 2011-02-10
15
760 Views
Last Modified: 2012-05-11
I have a big problem in which certain lines start with the @ symbol, the same as the start of line as the @ symbol use as the input record separator.

for example,

@test_scsi 1 <------ use as a input record separator
1. slslslslslslsls
@ this slslslslslslslsls  <--------- need to change this @ symbol to something different, pref. #
2. dkdkdkdkdkdkd
dkdkdkdkdkd
3. dkdkdkdkdkdk
@ trying again  <--------- need to change this @ symbol to something different, pref. #
@test_scsi 2 <------ use as a input record separator
1. slslslslslslsls
@ this slslslslslslslsls  <--------- need to change this @ symbol to something different, pref. #
2. dkdkdkdkdkdkd
dkdkdkdkdkd
3. dkdkdkdkdkdk
@ trying again  <--------- need to change this @ symbol to something different, pref. #
@test_scsi 3 <------ use as a input record separator
1. slslslslslslsls
@ this slslslslslslslsls  <--------- need to change this @ symbol to something different, pref. #
2. dkdkdkdkdkdkd
dkdkdkdkdkd
3. dkdkdkdkdkdk
@ trying again  <--------- need to change this @ symbol to something different, pref. #
@test_scsi 4 <------ use as a input record separator
1. slslslslslslsls
@ this slslslslslslslsls  <--------- need to change this @ symbol to something different, pref. #
2. dkdkdkdkdkdkd
dkdkdkdkdkd
3. dkdkdkdkdkdk
@ trying again  <--------- need to change this @ symbol to something different, pref. #
@test_scsi 5 <------ use as a input record separator
1. slslslslslslsls
@ this slslslslslslslsls  <--------- need to change this @ symbol to something different, pref. #
2. dkdkdkdkdkdkd
dkdkdkdkdkd
3. dkdkdkdkdkdk
@ trying again  <--------- need to change this @ symbol to something different, pref. #


Here's test the code I put together based on the pattern that the not needed @ symbol follows a line number above but not working. I'm not getting any output.

#!/usr/bin/perl

use strict;
use warnings;

$/='@';

open FH,'<','scsi_test' or die $!;

while (<FH>)
{
    if(/(^[1-40]\..+[^\n]+)\n(\^@.+[^\n]+)/ms)
    {
       print $2;
    }
}

0
Comment
Question by:areyouready344
  • 8
  • 4
  • 3
15 Comments
 
LVL 84

Assisted Solution

by:ozo
ozo earned 214 total points
ID: 34865614
if you want to change @s that are followed by space
perl -i.bak -pe 's/^@ /# /' scsi_test
0
 
LVL 26

Assisted Solution

by:wilcoxon
wilcoxon earned 286 total points
ID: 34865632
Or if all of your actual separators begin @test then you could set $/ = '@test' (rather than the $/ = '@' I think you currently have).
0
 

Author Comment

by:areyouready344
ID: 34865677
Ozo, i need to make a different between input record symbol of @ and the @ symbols at the wrong locations which are following the above number lines.
0
 
LVL 84

Accepted Solution

by:
ozo earned 214 total points
ID: 34865773
perl -MYAPE::Regex::explain -e 'print YAPE::Regex::Explain->new(qr/(^[1-40]\..+[^\n]+)\n(\^@.+[^\n]+)/ms)->explain'
The regular expression:

(?ms-ix:(^[1-40]\..+[^\n]+)\n(\^@.+[^\n]+))

matches as follows:
 
NODE                     EXPLANATION
----------------------------------------------------------------------
(?ms-ix:                 group, but do not capture (with ^ and $
                         matching start and end of line) (with .
                         matching \n) (case-sensitive) (matching
                         whitespace and # normally):
----------------------------------------------------------------------
  (                        group and capture to \1:
----------------------------------------------------------------------
    ^                        the beginning of a "line"
----------------------------------------------------------------------
    [1-40]                   any character of: '1' to '4', '0'
----------------------------------------------------------------------
    \.                       '.'
----------------------------------------------------------------------
    .+                       any character (1 or more times (matching
                             the most amount possible))
----------------------------------------------------------------------
    [^\n]+                   any character except: '\n' (newline) (1
                             or more times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \1
----------------------------------------------------------------------
  \n                       '\n' (newline)
----------------------------------------------------------------------
  (                        group and capture to \2:
----------------------------------------------------------------------
    \^                       '^'
----------------------------------------------------------------------
    @                        '@'
----------------------------------------------------------------------
    .+                       any character (1 or more times (matching
                             the most amount possible))
----------------------------------------------------------------------
    [^\n]+                   any character except: '\n' (newline) (1
                             or more times (matching the most amount
                             possible))
----------------------------------------------------------------------
  )                        end of \2
----------------------------------------------------------------------
)                        end of grouping
----------------------------------------------------------------------

Since there is no literal '^' character in your example, it would never match.
Also, since you are splitting on '@' the @ would be the last character in each record, so there would be no . or [^\n] following

perhaps you would prefer
    if(/(^[1-40]\..+[^\n]+)\n(^@.*[^\n]*)/ms)
    {
       print $1;
    }

or

$/='@test';

open FH,'<','scsi_test' or die $!;

while (<FH>)
{
    if(/(^[01-4]\..+?[^\n]+)\n(^@.*[^\n]*)/ms)
    {
       print $2;
    }
}

or

$/='@test';

open FH,'<','scsi_test' or die $!;

while (<FH>)
{
    s/(^\d\.[^\n]+\n)\@/$1#/msg;
    print;
}

0
 

Author Comment

by:areyouready344
ID: 34865867
there maybe a chance that @test maybe listed below the number lines. Can Perl grep be used in this case? Or is there another solution would involving the input record separator? Super Thanks.....
0
 

Author Comment

by:areyouready344
ID: 34865901
Can i just read in the whole file and search for that pattern by passing the @test input record separator?
0
 
LVL 26

Assisted Solution

by:wilcoxon
wilcoxon earned 286 total points
ID: 34865985
Personally, unless @test can only appear as a record separator or all separators are @test and all non-separators are @ followed by space, I'd either read the file in line-by-line and manually process it or (more probably) use Tie::File to treat the whole file as an array (and process it from there).
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 

Author Comment

by:areyouready344
ID: 34865989
I need the search for the pattern below regardless of the input record separator. Is this possible?

[1-40]\.*\n
@.*
0
 
LVL 26

Assisted Solution

by:wilcoxon
wilcoxon earned 286 total points
ID: 34866073
Sure...

m{[0-4]\.[^\n]+\n\@.*}ms

Changed [1-40] to [0-4] to make it more explicit what it does.
Changed \.* to \.[^\n]+ as the first would look for repeating literal periods.
0
 
LVL 26

Assisted Solution

by:wilcoxon
wilcoxon earned 286 total points
ID: 34866082
I'm unclear exactly what you're trying to do with that pattern so I'm not sure if it needs further modification or not.
0
 

Author Comment

by:areyouready344
ID: 34866283
That didn't work Wilcoxon because it list the input record separator if the number line is above it. I get the data, that is below the @input record separator from the exs server and don't wanna change it. Is regex useful in this situation?
0
 
LVL 84

Assisted Solution

by:ozo
ozo earned 214 total points
ID: 34866370
perl -0100i.bak -pe 's/(^\d\..*\n)@/$1#/m' scsi_test
0
 

Author Comment

by:areyouready344
ID: 34906942
thanks all, I fix this problem by taking Ozo suggestion in a previous case ticket by changing the input record separator from @text to __Data__ . The new record previous interference with the data records and solved this problem
0
 

Author Comment

by:areyouready344
ID: 34906950
The problem was with the structuring of the data records.
0
 

Author Closing Comment

by:areyouready344
ID: 34906982
the problem was with the structuring of the data records
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

Many time we need to work with multiple files all together. If its windows system then we can use some GUI based editor to accomplish our task. But what if you are on putty or have only CLI(Command Line Interface) as an option to  edit your files. I…
Email validation in proper way is  very important validation required in any web pages. This code is self explainable except that Regular Expression which I used for pattern matching. I originally published as a thread on my website : http://www…
Explain concepts important to validation of email addresses with regular expressions. Applies to most languages/tools that uses regular expressions. Consider email address RFCs: Look at HTML5 form input element (with type=email) regex pattern: T…
This tutorial gives a high-level tour of the interface of Marketo (a marketing automation tool to help businesses track and engage prospective customers and drive them to purchase). You will see the main areas including Marketing Activities, Design …

920 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

16 Experts available now in Live!

Get 1:1 Help Now