1 votes

Variables pour construire des modèles à utiliser avec sed

J'ai écrit une fonction bash pour imprimer des sections de texte enfermées entre des lignes correspondantes. ## mode: org y ## # End of org dans un fichier, avec une ligne vide entre les sections. Avant le ## il peut y avoir un nombre quelconque d'espaces.

Voici un exemple de fichier dont on peut extraire des informations.

file: test.sh

## mode: org
## * Using case statement
## # End of org
case $arg in
 ("V")
   echo "Author"
   ;;
 (*)
   ## mode: org
   ## ** Silent Error Reporting Mode (SERM) in getopts
   ## *** Detects warnings without printing built-in messages.
   ## *** Enabled by colon {:} as first character in shortopts.
   ## # End of org
   break
   ;;
esac

La sortie souhaitée serait

Code :

* Using case statement

** Silent Error Reporting Mode (SERM) in getopts
*** Detects warnings without printing built-in messages.
*** Enabled by colon {:} as first character in shortopts.

Voici la fonction que j'utilise

capture-org ()
{
  local efile="$1"

  local begsec="## mode: org"
  local endsec="## # End of org"

  sed -n "/^[[:space:]]*${begsec}$/,/^[[:space:]]*${endsec}$/s/ *//p'" "$efile" |
   sed 's/^'"${begsec}"'$/\n'"${begsec}"'/' |
   sed '/^'"${begsec}"'$/d' | sed '/^'"${endsec}"'$/d' | cut -c 3-
}

Je voudrais simplifier la fonction, en utilisant des variables pour construire des modèles. Mais j'ai besoin d'aide pour compiler les commandes ensemble de manière à ne pas avoir à appeler sed tant de fois.

Peut-être qu'en utilisant awk serait une meilleure stratégie.

capture-org ()
{
  local efile="$1"

  local begsec='^[[:space:]]*## mode: org$'
  local endsec='^[[:space:]]*## # End of org$'

  sed -n "/${begsec}/,/${endsec}/s/ *//p" "$efile" |
   sed 's/^## # End of org$/## # End of org\n/' |
   sed '/^## mode: org$/d' | sed '/^## # End of org$/d' | cut -c 3-
}

1voto

Stewart Points 1385

J'utiliserais en effet quelque chose de plus sophistiqué pour cela. Comme awk :

$ awk -v start="$begsec" -v end="$endsec" \
    '{ 
        if($0~start){want=1; next} 
        if($0~end){want=0; print ""; next} 
        gsub(/\s*#+\s*/,""); 
     } want' file
* Using case statement

** Silent Error Reporting Mode (SERM) in getopts
*** Detects warnings without printing built-in messages.
*** Enabled by colon {:} as first character in shortopts.

Ou, en utilisant votre dernière fonction là-bas comme modèle :

capture-rec ()
{

  local begsec='## mode: org'
  local endsec='## # End of org'

  awk -v start="$begsec" -v end="$endsec" \
    '{ 
        if($0~start){want=1; next} 
        if($0~end){want=0; print ""; next} 
        gsub(/\s*#+\s*/,""); 
     } want' "$1"
}

Une mise en garde qui peut être importante est que cela ne nécessite pas que le $begsec y $endsec soient les seules choses sur la ligne autres que les espaces blancs de tête comme votre approche l'a fait, il les cherche simplement n'importe où sur la ligne. Je suppose que ce n'est pas très important compte tenu de ce que vous recherchez, mais si c'est le cas, vous pouvez utiliser cette méthode qui supprimera les espaces au début et à la fin de la ligne avant la correspondance :

capture-rec ()
{

  local begsec='## mode: org'
  local endsec='## # End of org'

    awk -v start="$begsec" -v end="$endsec" \
    '{ 
        sub(/^[[:space:]]*/,"");
        sub(/[[:space:]]*$/,"");
        if($0==start){ want=1; next} 
        if($0==end){   want=0; print ""; next} 
        gsub(/\s*#+\s*/,""); 
     } want' "$1"
}

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X