2017-01-28 3 views
0

La solution déjà affichée d'utiliser awk ou sed est assez standard et aide au cas où quelque chose ne fonctionnerait pas correctement.Un script pur Bash Cuting qui ne fournit pas un travail efficace

comme pour:

StringStr="ValueA:ValueB,ValueC:ValueC" ; 

echo ${StringStr} | gawk -F',' 'BEGIN{}{for(intx=1;intx<=NF;intx++){printf("%s\n",$(intx))}}END{}' 

ne produisent le même résultat, mais un utilisateur restreint qui peut s'y connecter en son compte et ont moins option comme pas autorisés à utiliser awk ou gawk pour une raison spécifique ne doit produire quelque chose qui doit fonctionner à chaque fois.

Pour des raisons efficace je développer ma propre bibliothèque de fonctions Bash sur github.com et tomber sur une technique qui ne fonctionne pas comme on le suppose et ici un exemple de travail:

Cette technique utiliser le modèle préfixe « Supprimer correspondant Bash 'et' Supprimer le motif de suffixe correspondant '. Le but est d'obtenir une chaîne d'informations chaînées pour utiliser le plus simplement possible l'élément bash-shell pour extraire l'élément inséré.

Par la présente j'ai première déclaration pour obtenir une chaîne d'un format spécifique: Ex:

StringPattern="__VALUE1__:__VALUE2__," 

Le format suppose l'ajout de la chaîne, de nombreux modèles de type StringPattern. Le reste ',' sera utilisé pour diviser et séparer la chaîne en VALUE1: VALUE2.

comme StringStorage tiendra à plusieurs reprises, analysable StringPattern, voici 2 exemples: 1 - échantillon 1

StringPattern="VariableA:InformationA," 
StringStorage="${StringStorage}${StringPattern}" ; 

2 - échantillon 2

StringPattern="VariableB:InformationB," 
StringStorage="${StringStorage}${StringPattern}" ; 

A ce moment, StringStorage tenir correctement ces informations :

StringStorage="VariableA:InformationA,VariableB:InformationB," 

Maintenant avec StringStorage, le bas algorithme h fait d'un mélange de « supprimer le motif de préfixe correspondant » et « Supprimer le motif de suffixe correspondant » ne fonctionne pas pour ce cas:

### Description of IntCsvCount 
### does remove all chosed Comma Separated value ',' from StringStorage 
### and subtract from the original length the removed result from this 
### subtraction. This produce IntCsvCount == 2 
IntCsvCount=$(cstr=${StringStorage//,/} ; echo $((${#StringStorage} - ${#cstr}))) ; 

### Description of 
### Will be re Variable used to put the Extracted sequence. 
bstr="" ; 

### Description of for 
### Received information from IntCsvCount it should count 
### from 0 to Last element . This case it's ${IntCsvCount}-1 or 1 in 
### my example. 

for ((intx=0 ; intx <= ${IntCsvCount}-1 ; intx++)) ; do 
    ### This extracting First Segment based on 
    ### Remove matching suffix pattern ${parameter%word} where 
    ### work is ${astr#*,} (Remove matching prefix pattern) of 
    ### everything in $astr until find a ',' . 
    bstr=${astr%*${astr#*,}} ; 
    ### Destroying the $bstr part in by starting the astr to position of 
    ### the end of size equivalent of bstr size (${#bstr}), end position is 
    ### equal to [ Highest-String size ] - [ Shortest-String size ] 
    astr=${astr:${#bstr}:$((${#astr} - ${#bstr}))} ; 
    echo -ne "Element: ${bstr}\n" ; 
done 

Cela devrait produire la réponse suivante.

Element: VariableA:InformationA, 
Element: VariableB:InformationB, 

Mettre cela en fonction ne demandera de changer le CSV par « : » et laisser extraire le « variableA » et « informationa ».

Le problème commence à l'aide d'une chaîne avec un non uniforme. Comme observé sur ce tableau, l'exemple d'une phrase et la coupe d'une partie devraient travailler sur une corde non-uniforme, mais ici un échantillon qui ne fonctionne pas.Et je n'ai plus d'un conseiller à la main d'utiliser gawk, sed, même coupé mais de cet algorithme, il ne fonctionne pas avec cet exemple:

astr="master|ZenityShellEval|Variable declaration|Added Zenity font support to allow choosing both font-name and size and parsing the zenition option, notice --font option require a space between font and size.|20170127|" 

comming de

astr=$(zenity --width=640 --height=600 --forms --show-header --text="Commit Message" --add-entry="Branch name" --add-entry="function" --add-entry="section" --add-entry="commit Message" --add-calendar="Commit Date" --forms-date-format="%Y%m%d" --separator='|') ; 

Je Faire respecter aussi la sortie doit ressembler à ce que StringPattern devrait ressembler: astr = "$ {astr} |" ;

Le même code, à l'exception de CSV (Comma Separated Value), est passé de ',' à '|'

IntCsvCount=$(cstr=${astr//|/} ; echo $((${#astr} - ${#cstr}))) ; 
bstr="" ; 
for ((intx=0 ; intx <= ${IntCsvCount}-1 ; intx++)) ; do 
    bstr=${astr%*${astr#*|}} ; 
    astr=${astr:${#bstr}:$((${#astr} - ${#bstr}))} ; 
    echo -ne "Element: ${bstr}\n" ; 
done 

Si cette sortie de temps générer la sortie suivante:

Element:master|ZenityShellEval|Variable declaration|Added Zenity font support to allow choosing both font-name and size and parsing the zenition option, notice --font option require a space between font and size.|20170127| 
Element: 
Element: 
Element: 

Y at-il une raison pour laquelle il ne devrait pas travailler chaque fois?

+3

Ceci est assez difficile à suivre. Pouvez-vous le simplifier à votre entrée, la sortie réelle et attendue, et quel code vous avez essayé d'obtenir ce résultat. – 123

Répondre

0

Donc, vous avez publié ce script AWK:

BEGIN{}{for(intx=1;intx<=NF;intx++){printf("%s\n",$(intx))}}END{} 

Si je comprends bien, vous dites qu'il fait exactement ce que vous voulez, et le seul problème est que vous ne voulez pas compter sur AWK?

Dans ce cas, vous êtes vraiment en train de rendre cela plus compliqué que nécessaire. Vous pouvez utiliser la fonctionnalité sous-chaîne-remplacement de Bash directement:

str=ValueA:ValueB,ValueC:ValueC 
printf '%s\n' "${str//,/$'\n'}" 
+0

Le script awk était une alternative, à ma connaissance, utilisée pour comptabiliser le trafic provenant d'iptable pour un fournisseur web. Mais comme mentionné précédemment, c'était seulement une alternative, et en fait c'était pour garder une solution de travail en moins de 2 lignes: 'bstr = $ {astr% * $ {astr # *}}}; astr = $ {astr: $ {# bstr}: $ (($ {# astr} - $ {# bstr}))}; '. Cette solution peut faire apparaître par CSV l'élément le plus à droite en même temps jusqu'à ce que la chaîne à l'intérieur de astr devienne vide.C'est efficace et nécessite moins de cpu-cycle par itération. Je devrais publier quelque chose à l'intérieur de mon github Fnct.D c'est un effort de développement rapide et d'être clair. –

0

Si je comprends la fin de votre question, vous avez une chaîne comme astr="master|ZenityShellEval|Variable declaration|Added Zenity font support to allow choosing both font-name and size and parsing the zenition option, notice --font option require a space between font and size.|20170127|" , et vous voulez que la sortie suivante:

Element: master 
Element: ZenityShellEval 
Element: Variable declaration 
Element: Added Zenity font support to allow choosing both font-name and size and parsing the zenition option, notice --font option require a space between font and size. 
Element: 20170127 

Le la manière la plus simple que je pourrais penser à faire ceci est la suivante:

s="${astr%|}"; echo "Element: ${s//|/$'\n'Element: }"; 

En outre, ne pas oublier les tableaux! Je pense qu'ils vous seront utiles pour ce que vous travaillez. Ce qui suit produit également la sortie désirée:

(IFS='|'; declare -a a=(${astr}); printf "Element: %s\n" "${a[@]}") 

Bash Hackers Wiki has a great page on arrays, que je recommande de regarder plus.

+0

2 choses les plus importantes à retenir 'bstr = $ {astr% * $ {astr # * |}}; astr = $ {astr: $ {# bstr}: $ (($ {# astr} - $ {# bstr}))}; ', fonctionnait finalement Je pense que c'est quelque chose avec de la mémoire et une fois les problèmes résolus, ça a marché donc soit sans avoir de doute mais partageant une méthode pour extraire efficacement le CSV le plus à gauche avec moins de déclaration, moins de contournement. Avec tableau, j'aime utiliser 'declare -a Array = ($ {astr // | /});' Il élargit CSV par l'espace et le tableau doit le diviser en éléments. Exiger d'ajouter un élément 'pour $ {Array [@]}; fais écho $ {item}; fait »où nous sommes hors de l'efficacité pour 3 lignes ajoutées. –

0

est ici le même parcours sur les derniers thèmes:

IFS="|" read -ra arr<<<"${astr}" 
printf "Element: %s\n" "${arr[@]}" 

Je pensais que je voudrais ajouter que votre awk d'origine est un peu ballonné à:

echo -n "ValueA:ValueB,ValueC:ValueC" | awk '1' RS="," 

Et bien sûr, awk pour solution actuelle:

awk 'NF && $0 = "Element: " $0' RS="|" <<<"$astr"