Puncte:1

Variabile pentru construirea de modele pentru utilizare cu sed

drapel jp

Am scris o funcție bash pentru a imprima secțiuni de text incluse între linii care se potrivesc ## modul: org și ## # Sfârșitul organizației într-un fișier, cu o linie goală între secțiuni. Inainte de ##, poate exista orice număr de spații.

Iată un exemplu de fișier din care să extragă informații.

fișier: test.sh

## modul: org
## * Folosind instrucțiunea case
## # Sfârșitul organizației
caz $arg in
 ("V")
   ecou "Autor"
   ;;
 (*)
   ## modul: org
   ## ** Modul de raportare silențioasă a erorilor (SERM) în getopts
   ## *** Detectează avertismente fără a tipări mesaje încorporate.
   ## *** Activat de două puncte {:} ca prim caracter în opțiunile scurte.
   ## # Sfârșitul organizației
   pauză
   ;;
esac

Ieșirea dorită ar fi

Cod:

* Folosind declarația caz

** Modul de raportare silențioasă a erorilor (SERM) în getopts
*** Detectează avertismente fără a imprima mesaje încorporate.
*** Activat de două puncte {:} ca prim caracter în shortopts.

Iată funcția pe care o folosesc

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

  local begsec="## mod: org"
  local endsec="## # Sfârșitul organizației"

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

Aș dori să simplific funcția, folosind variabile pentru a construi modele. Dar am nevoie de asistență pentru a compila comenzi împreună, astfel încât să nu fiu nevoit să apelez sed de atâtea ori.

Poate folosind awk ar fi o strategie mai bună.

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

  local begsec='^[[:space:]]*## mod: org$'
  local endsec='^[[:space:]]*## # Sfârșitul org$'

  sed -n "/${begsec}/,/${endsec}/s/ *//p" "$efile" |
   sed 's/^## # Sfârşitul org$/## # Sfârşitul org\n/' |
   sed '/^## modul: org$/d' | sed '/^## # Sfârşitul org$/d' | taie -c 3-
}
Puncte:1
drapel cn

Într-adevăr, aș folosi ceva mai sofisticat pentru asta. Ca awk:

$ awk -v start="$begsec" -v end="$endsec" \
    '{ 
        if($0~start){want=1; Următorul} 
        if($0~end){want=0; imprimare ""; Următorul} 
        gsub(/\s*#+\s*/,""); 
     } vreau' fișier
* Folosind declarația caz

** Modul de raportare silențioasă a erorilor (SERM) în getopts
*** Detectează avertismente fără a imprima mesaje încorporate.
*** Activat de două puncte {:} ca prim caracter în shortopts.

Sau, folosind ultima ta funcție acolo ca șablon:

capture-rec ()
{

  local begsec='## mod: org'
  local endsec='## # Sfârșitul organizației'

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

Un avertisment care poate fi important este că acest lucru nu necesită ca $begsec și $endsec fie singurele lucruri pe linie, în afară de spațiul alb de conducere, așa cum a făcut abordarea dvs., pur și simplu le caută oriunde pe linie. Presupun că aceasta nu este o problemă foarte mare, având în vedere ceea ce căutați, dar dacă este, puteți utiliza acest lucru în schimb, care va elimina spațiile albe la începutul și la sfârșitul liniei înainte de potrivire:

capture-rec ()
{

  local begsec='## mod: org'
  local endsec='## # Sfârșitul organizației'

    awk -v start="$begsec" -v end="$endsec" \
    '{ 
        sub(/^[[:spațiu:]]*/,"");
        sub(/[[:spațiu:]]*$/,"");
        if($0==start){ want=1; Următorul} 
        if($0==end){ want=0; imprimare ""; Următorul} 
        gsub(/\s*#+\s*/,""); 
     } vreau" "$1"
}
drapel jp
Tipărește alte părți ale fișierului care preced prima linie potrivită
drapel jp
Am nevoie ca ele să fie singurele lucruri de pe linie, altele decât spațiile albe de început, pentru că ar fi preluate dacă aș rula comenzile din același fișier (preluând `local begsec='## mode: org'` și `local endsec ='## # Sfârșitul organizației'`).
terdon avatar
drapel cn
@Fatipati vedeți răspunsul actualizat pentru o versiune care funcționează numai pe liniile în care beg- și endsec sunt întreaga linie, cu excepția spațiului alb de început și de final. Dacă acest lucru nu funcționează așa cum era de așteptat, vă rog să-mi arătați un fișier în care eșuează, ca să înțeleg de ce.
Puncte:0
drapel cn

Această comandă cu o singură linie din script-ul dvs. ar putea face treaba:

awk '/## mode/{flag=1;next} /## # End/{flag=0} flag' extract.txt | tr -d /#/ | awk '$1=$1'

* Folosind declarația caz
** Modul de raportare silențioasă a erorilor (SERM) în getopts
*** Detectează avertismente fără a imprima mesaje încorporate.
*** Activat de două puncte {:} ca prim caracter în shortopts.

Al doilea awk elimină pur și simplu spațiile de început.

drapel jp
A menționat, primesc mai multe linii tipărite între părțile „început” și „sfârșit”. Acest lucru se datorează faptului că trec același fișier în care am codul și astfel funcția `capture-org`.
drapel jp
Trebuie să potrivesc exact ca în cazul modelelor `^[[:space:]]*## mode: org$` și `^[[:space:]]*## # Sfârșitul org$`.

Postează un răspuns

Majoritatea oamenilor nu înțeleg că a pune multe întrebări deblochează învățarea și îmbunătățește legătura interpersonală. În studiile lui Alison, de exemplu, deși oamenii își puteau aminti cu exactitate câte întrebări au fost puse în conversațiile lor, ei nu au intuit legătura dintre întrebări și apreciere. În patru studii, în care participanții au fost implicați în conversații ei înșiși sau au citit transcrieri ale conversațiilor altora, oamenii au avut tendința să nu realizeze că întrebarea ar influența – sau ar fi influențat – nivelul de prietenie dintre conversatori.