Perl help in deleting array that contains 0

Hi,

I have map co-ordinates GDF data like the below:

{123, 2, 244}, {233, 0, 432}, {0, 233, 24}, {353, 21, 0}, {22, 756, 92}, {281, 0, 211}, {211, 645, 22}, {310, 23, 0}

I need to use perl script to store these values into an array and delete from the array whose indices having value 0 anywhere

So, finally I need to get the result as:

{123, 2, 244}, {22, 756, 92}, {211, 645, 22}

I am a newbie to Perl. How to store array of arrays in Perl?

I have come across that to erase an array element we can use splice and delete and for pattern matching, we can use "=~" operator. Please help me in writing this script.

% perl -F'/(?<=}),\s/' -alne 'print join ", ", grep {!/\b0\b/} @F' INPUTFILE
{123, 2, 244}, {22, 756, 92}, {211, 645, 22}
2 Likes

Wow!! amazing... cute one-liner.

If possible could you please explain it?

Ok, I'll try but my English is not good at all.

Perl switches (perldoc perlrun):
"-n" reads lines from @ARGV (that is INPUTFILE) to $_ and "-l" removes and adds (when printing) newline chars. "-a" splits $_ to @F array according to a regex from "-F" option

"grep {! RE} @F" filters all elements from the array (elements are strings - "{123, 0, 111}" and so on) where it's not true that 0 is a "word" (not in any numbers like 10, 101, etc.).

Then we join the ready list to a string with ", " as the separator and print it.

1 Like

Thanks yazu a ton, in shedding light on this !!

But still this RE is obscure :frowning:

(?<=}),\s

And, what this "(?={)" would mean?

We can't use spaces in -F on the command line - so \s.
If we use ',\s' as the separator - it will split to "{120", "123}" and so on.
If we use '},\s' as the separator we lose "}" in array elements.

There is a lookbehind possibility in perl: /(?<=XXX)YYY/ It means we use YYY as RE but only if before YYY there is XXX. It's just like XXXYYY but XXX does not count for use RE for splitting or substitution or matching (for memory variables like $&, etc.). In perl there are lookahead (?=XXX) and negative lookbehind(lookahead) capabilities also.

 perl -nle '$,=",";print /\{[^0]*\}/g' filename
2 Likes

You can lose elements with 210 and so on:

% echo '{210, 645, 22}, {310, 23, 0}'| perl -nle '$,=",";print /\{[^0]*\}/g'

But so it works:

perl -nle '$,=", "; print grep { ! /\b0\b/ } /\{.*?\}/g' 

Thank you for the idea. It's simpler.

Hi yazu, suppose if the given input data is present between the pair of braces (enveloped by braces) (i.e) {{...}, {...}, {...}} then I have noticed a flaw that when the matching expression is a corner case or the last element in the array then your code deletes the final '}' (outermost closing brace) also. Consider: {{123, 2, 244}, {22, 756, 92}, {211, 0, 22}}

Outputs: {{123, 2, 244}, {22, 756, 92} --> closing brace is missing. I need to get the closing '}' also. Please help.

$
$
$ cat f7
{123, 2, 244}, {233, 0, 432}, {0, 233, 24}, {353, 21, 0}, {22, 756, 92}, {281, 0, 211}, {211, 645, 22}, {310, 23, 0}
{{123, 2, 244}, {22, 756, 92}, {211, 0, 22}}
$
$
$
$ perl -plne 's/,* *{[^}{]*? *\b0,*.*?}//g' f7
{123, 2, 244}, {22, 756, 92}, {211, 645, 22}
{{123, 2, 244}, {22, 756, 92}}
$
$
$

tyler_durden

Thank you durden_tyler, its awesome!! worked like charm :slight_smile:

If possible, could you explain us the logic of the RE?