0
votes

la substitution de SED avec une condition "ou" ne semble pas fonctionner

My SED Regex "ou" ne semble pas fonctionner lorsqu'un insert / substitution est impliqué. Compte tenu du fichier de données suivant, si un mot clé existe après le cinquième champ, je souhaite insérer un retour de chariot avant le mot-clé. L'idée est alors d'imprimer les lignes individuelles. Je comprends que Python, Perl, etc. serait mieux, mais Bourne Shell est l'exigence.

data.txt: p> xxx pré>

script.sh p> xxx pré>

la sortie souhaitée: p>

-> first('echo hello') 
-> second('ls /tmp')

-> second('ls -la /home') 
-> forth('ls /tmp')

-> first ('touch /tmp/hello')

-> fifth('echo hello world')
-> first('ls /etc')
-> third ('mkdir -p /tmp/blah')


2 commentaires

Bash n'est pas la coque de Bourne, qui pratiquement personne ne l'utilise plus.


Bash: "Bourne à nouveau shell". Je suppose qu'il est facile de les mélanger.


4 Réponses :


1
votes

dans SED sous -E , les parenthèses de regroupement ne doivent pas être répertoriées. La parenthèse recul correspondante correspond au littéral.

De plus, votre affectation à $ Scriptlets manque une parenthèse de fermeture pour la substitution de commande. Aussi, êtes-vous sûr que vous souhaitez utiliser la substitution de commande deux fois, une fois dans l'affectation et une fois dans la pour boucle?

Enfin, vous vouliez probablement dire pendant la ligne de lecture au lieu de pour la ligne de lecture ce qui n'a aucun sens.


0 commentaires

0
votes

cela a commencé comme un commentaire mais trop longtemps. Voir Réponse de Choroba pour une solution appropriée.

Il y a un tas de choses qui ne va pas ici.

  1. pour la ligne de lecture n'est pas valide; Vous vouliez probablement dire en lecture ligne .
  2. scriptlets = $ (... manque une paren de fermeture.
  3. $ (scriptlets) n'est probablement pas ce que vous voulez - vous vouliez probablement dire $ {scriptlets}
  4. echo $ line est discutable. Vous voulez probablement citer cette variable
  5. bash n'est pas identique à la coquille de Bourne, bien qu'elle soit compatible. Par exemple, la coque de Bourne ne prend pas en charge les chaînes de style C, $ '...' ... ', comme dans ifs = $' \ n '. .
  6. \ n est un caractère de nouvelle ligne, tandis que \ r est un retour de chariot. (C'est plus d'un Nitpick, mais cela pourrait confondre des gens de lire la question.)

    essayez d'utiliser shellcheck à déboguer.


0 commentaires

0
votes

Apparemment, vous ne pouvez pas combiner le SED "ou" et substitution / insérer ensemble. Par conséquent, j'avais besoin de casser la déclaration SED dans des déclarations individuelles.

scriptlets=$(echo $line | cut -d ' ' -f 6- | sed -e 's/ first/\'$'\nfirst/' -e 's/second/\'$'\nsecond/' -e 's/ third/\'$'\nthird/' -e 's/forth/\'$'\nforth/' -e 's/ fifth/\'$'\nfifth/')


0 commentaires

0
votes

Par défaut, SED utilise la syntaxe d'expression régulière "BASIC" qui ne prend pas en charge l'alternance (la "ou" dont vous parlez). Pour utiliser une alternance, utilisez sed -e code> et "étendue" Syntaxe Regex. De plus, votre syntaxe pour insérer une nouvelle ligne dans le motif de remplacement est brouillée. Essayez cela à la place:

#!/bin/bash

while read scriptlet; do
    echo "-> $scriptlet"
done < <(cut -d ' ' -f 6- data.txt | \
         sed -E $'s=(first|second|third|forth|fifth)=\\\n\\1=g' )
echo 


0 commentaires