samedi 28 janvier 2017

A pure Bash Cuting script that do not provide efficient work

Already posted solution of using awk or sed are quite standard and help in case something did not work correctly.

like for a :

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

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

do produce the same result, but a restricted user that can log into it's account and have fewer option like not allowed to used awk or gawk for a specific reason does have to produce something that have to work every-time.

For efficient reason I do develop my own Bash Function Library on github.com and fall on a technique that do not work as supposed and here a working example:

This technique use the Bash 'Remove matching prefix pattern' and 'Remove matching suffix pattern'. The goal is to get a string of chained information to use a simple as possible the bash-shell element to extract-out inserted element.

By the present I do have first statement to obtain a String out of a specific format: Ex:

StringPattern="__VALUE1__:__VALUE2__,"

The format suppose adding in chain, many Pattern of type StringPattern. The remain ',' will be used to split and separate the string back in VALUE1:VALUE2 form .

like StringStorage will hold many times, parsed StringPattern, here 2 examples: 1 - sample 1

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

2 - sample 2

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

At this moment, StringStorage hold properly this information:

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

Now with StringStorage, the bash algorithm made out of a mix of 'Remove matching prefix pattern' and 'Remove matching suffix pattern' does work for this case :

### 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

This should produce the following answer.

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

Putting this into a function will require only to change the CSV by ':' and let extract the 'VariableA' and 'InformationA'.

The problem start using a String with non uniform. As observed on this board, example of a sentence and cutting a part should work on non-uniform string, but here a sample that do not work. And I do have more than one advise in hand from using gawk, sed, even cut but from this algorithm it does not work with this sample :

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 from

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='|' ) ;

I am also enforcing the output to look like what StringPattern should look like: astr="${astr}|" ;

The same code except CSV (Comma Separated Value) was changed from ',' to '|'

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

Where this time output generate following output:

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:

Is there some reason why it should not work every time ?

Aucun commentaire:

Enregistrer un commentaire