web-dev-qa-db-fra.com

Y a-t-il un moyen de supprimer, mais seulement des crochets imbriqués?

Dis que j'ai une corde comme ça

[[["q", "0"], "R"], "L"], ["q", [["1", "["], "]"]], [["q", ["2", "L"]], "R"], ["q", ["3", ["R", "L"]]]

et je veux enlever toutes les crochets imbriquées

["q", "0", "R", "L"], ["q", "1", "[", "]"], ["q", "2", "L", "R"], ["q", "3", "R", "L"]

Je comprends comment un algorithme pourrait être écrit que cela fait cela en poussant et en poussant une pile ou simplement incrémentation et en décrémentant un compteur, mais je suis curieux s'il y a un moyen de le faire juste avec des outils de base comme sed ou awk.

9
lokus

Ce qui suit est un autre moyen d'aplatir les crochets cette fois-ci à l'aide d'une regex non récursive.

echo "....." |\
Perl -lne '
  my $re = qr{\[ (?{ local $a = 1 })
    (?:(?(?{ ! $a })(?!))
       (?:
         \[(?{ local $a=$a+1 }) |
         \](?{ local $a=$a-1 }) |
         (?>"[^"]*") |
         (?>[^]"[]+) 
      )
    )+
  (?(?{ $a })(?!))
}x;
print s/($re)/"[" . 
  $1 =~ s{([^"]*(?:"|$))}{
    $|-- ? $1 : $1 =~ tr:][::dr;
  }regx
. "]"/regx;
' 
2
Rakesh Sharma

Nous pouvons résoudre ce problème au moyen d'un paradigme de programmation fonctionnelle une fois que nous réalisons que la chaîne d'entrée est une liste de listes valide (@LOLS).

Nous stockons donc la chaîne dans un fichier texte et "faire" l'invoque à l'intérieur du code PERL. Ce qu'il fait, c'est une structure de données Perl valide gratuitement pour nous.

Maintenant, nous utilisons simplement une commande de carte récursive pour décomposer la liste dans leurs éléments individuels. Puis les décorer entre des citations et des virgules les séparent.

#! /bin/env bash 
echo '@::LoLs = ([[["q", "0"], "R"], "L"], ["q", [["1", "["], "]"]], [["q", ["2", "L"]], "R"], ["q", ["3", ["R", "L"]]])' > code.pl

Perl -wMstrict   -le '
  local $" = ", "; #list separator 
  use constant A => q[ARRAY];
  do "./code.pl";
  print join q[, ], map { qq([$_]) } 
    map {
      $_[0] ||= sub {
        "@{[map {
            +ref eq A ? $_[0]->($_[0],@$_) : qq(\"$_\");
          } splice @_,1]}"; #end inner map
    };  #end sub
    $_[0]->($_[0],$_);
  } @::LoLs; # end outer map 
'

résultat :

["q", "0", "R", "L"], ["q", "1", "[", "]"], ["q", "2", "L", "R"], ["q", "3", "R", "L"]
0
Rakesh Sharma