1832509 Members
4559 Online
110043 Solutions
New Discussion

inserting delimiters

 
SOLVED
Go to solution
cam9269
Regular Advisor

inserting delimiters

Hi Guys,

I need advise on how to format strings in a specific way.

I have this data extracted from the passwd file

user1,YNNNNNNNNNNNNNNNNNNN
user2,YNNNNNNYYNNNNNNNNNNN

field1 = username
field2 = user flags in the descriptions field

from the above format I wanted to create this output:

user1,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
user2,Y,N,N,N,N,N,N,Y,Y,N,N,N,N,N,N,N,N,N,N

TIA!
14 REPLIES 14
Hein van den Heuvel
Honored Contributor
Solution

Re: inserting delimiters

$ perl -lpe'($u,$f)=split /\W/; $_=join q(,),$u,split(//,$f)'

-lpe = loop trhough input and print $_ with newline

First split on non-Word (The , and the new-line) saving username in $u, flags in $f.

The re-join with commas, that username, and the flags where those are re-split on 'nothing'.

Enjoy,
Hein.


Dennis Handly
Acclaimed Contributor

Re: inserting delimiters

I you have exactly 20 and you don't want to write a script to break them up, you can use sed:
================================================
sed -e 's/\(.*,\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\1\2,\3,\4,\5,\6,\7,\8,\9,/' \
-e 's/\(.*,.,.,.,.,.,.,.,.,\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)\(.\)/\1\2,\3,\4,\5,\6,\7,\8,\9,/' \
-e 's/\(.*,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,.,\)\(.\)\(.\)\(.\)\(.\)/\1\2,\3,\4,\5/'
OFC_EDM
Respected Contributor

Re: inserting delimiters

Here's one example at an easier level.
Disadvantage is it calls multiple sed statements. But it's easier to understand if you're just starting out.

cat testdata
user1,YNNNNNNNNNNNNNNNNNNN
user2,YNNNNNNYYNNNNNNNNNNN

cat testdata | tr "," " " | sed -e 's/Y/Y /g' | sed -e 's/N/N /g' | sed -e 's/ /,/g' | sed -e 's/$,//g'

Output
user1,Y,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N,N
user2,Y,N,N,N,N,N,N,Y,Y,N,N,N,N,N,N,N,N,N,N,N

Approach
Decided a space will be the final Field delimeter.
So replaced that first comma with a space
tr "," " "
Then put a space beside all Y's and N's
sed -e 's/Y/Y /g' | sed -e 's/N/N /g'
Then replaced all spaces with a comma
sed -e 's/ /,/g'
And then finally removing the comma that would be left at the end of the string from the previous step
sed -e 's/,$//g'
The Devil is in the detail.
cam9269
Regular Advisor

Re: inserting delimiters

Well done guys! Many, many thanks for the prompt replies. I really need to get my scripting level up more.

These options are superb!

Thanks again!
cam9269
Regular Advisor

Re: inserting delimiters

Thanks very much for the explanations KU. You deserve more that 10pts for this. :)
cam9269
Regular Advisor

Re: inserting delimiters

Also to Hein, though I'm a newbie's newbie when it comes to perl scripting. Appreciate it! it'll be my first 'hard' script to understand with perl.
Steven Schweda
Honored Contributor

Re: inserting delimiters

> Disadvantage is it calls multiple sed
> statements.

It doesn't need to. Multiple "-e" options
should do the job with one "sed".

Of these two:

> [...] 's/$,//g'
> [...] 's/,$//g'

the second one works better. And is "tr"
really needed?

bash$ echo 'user1,YNNNNNNNNN' | \
sed -e 's/,/ /' -e 's/Y/Y /g' -e 's/N/N /g' -e 's/ /,/g' -e 's/,$//g'
user1,Y,N,N,N,N,N,N,N,N,N
Dennis Handly
Acclaimed Contributor

Re: inserting delimiters

>Thanks very much for the explanations

I can explain my regular expressions:
1) It captures everything up to the first comma and puts it back.
2) It then captures 8 characters and puts each back followed by a ",".
3) Since \# only works for 1..9, it does 8 more, after first accepting the first 8.
4) Then it does the final 4 after accepting the first 16.
Steven Schweda
Honored Contributor

Re: inserting delimiters

> [...] Closing thread now

Ha! As if that could stop me...

bash$ echo 'user1,YNNNNNNNNN' | \
sed -e 's/,/ /' -e 's/\([NY]\)/\1 /g' -e 's/ /,/g' -e 's/,$//g'
user1,Y,N,N,N,N,N,N,N,N,N
Hein van den Heuvel
Honored Contributor

Re: inserting delimiters

My solution is best explained by taking out all shortcuts:

$ perl -lpe'($u,$f)=split /\W/; $_=join q(,),$u,split(//,$f)'

Really is...

while ($line = ) {
($user, $flags) = split (/\W/, $line);
@letters = split(//, $flags);
$new_line = join ',' , $user, @letters;
print $new_line, "\n";
}

Hein.


cam9269
Regular Advisor

Re: inserting delimiters

appreciate your enthusiasm Steven! I picked up on your advice :)
Thanks for the notes Hein! Will likely to play and consider it in the code too

Cheers!
Dennis Handly
Acclaimed Contributor

Re: inserting delimiters

>Steven: As if that could stop me...
>echo 'user1,YNNNNNNNNN' | \
sed -e 's/,/ /' -e 's/\([NY]\)/\1 /g' -e 's/ /,/g' -e 's/,$//g'

It is obvious this isn't going to work if the user name is like "YESNO".

I'm also not sure why you want to change to spaces then back?
Note: the "g" in 's/,$//g' is useless.
cam9269
Regular Advisor

Re: inserting delimiters

i really, really appreciate all the inputs! :)
Dennis Handly
Acclaimed Contributor

Re: inserting delimiters

You can also use awk. Unfortunately I can't get split to work there with an empty RE.
awk -F, '
{
printf $1 ","
for (i=1; i < 20; ++i)
printf substr($2,i,1) ","
print substr($2,20,1)
} '