0

Here is my source :

TABLE;APGFPOLI;

And here is the output that i want :

01 APGFPOLI. 

So what i am trying to do is remove "TABLE" and add 01 before "APGFPOLI". I need to do it for the first line only. So i tried to do :

    #!/bin/bash

#Fichier Source
fichier="APGFPOLI.des.txt"

champAdd="05 "

if [[ -f "$fichier" ]]
then
    
    # read it
    sed -i '1 s/TABLE//' $fichier |sed -i 's/CHAR/PIC X/' $fichier | sed -E '/Numérique/s/;Numérique\s+([^;]*)/;PIC 9(\1)/' $fichier | while IFS=';' read -r nomChamp format libelle
    do
        echo \* $libelle
        echo $champAdd $nomChamp $format.
    done > test.txt
fi

As you can see, my first sed is supposed to remove TABLE but it dont work. i also do a echo for my others line but i'd like to echo this specific first line too.

Here is the output my bash gives me :

  *
05 TABLE APGFPOLI.

Here is my full source if it helps :

TABLE;APGFPOLI;
Contrat;CHAR(16);Numéro du contrat
Libelle;CHAR(30);Libellé du contrat
DtCreation;CHAR(8);Date de création
DtMaj;CHAR(8);Date de dernière MAJ
DtEffet;CHAR(8);Date d'effet adhésion
MotifAdh;CHAR(2);Motif d'adhésion
DtRadiation;CHAR(8);Date de radiation
DtEnrRad;CHAR(8);Date enregistrement radiat
MotifRad;CHAR(2);Motif de radiation
MtPrime;Numérique 8.2;Montant prime d'origine
DtEffetSusp;CHAR(8);Date d'effet de suspension
DtFinSusp;CHAR(8);Date de fin de suspension
MotifSusp;CHAR(2);Motif de suspension
DestBord;CHAR(1);Destinataire du bordereau
CdDest;CHAR(5);Code du destinataire
NivRupBord;CHAR(1);Niveau rupture bordereau
BordCETIP;CHAR(1);Bordereau CTIP
EnvBordNom;CHAR(1);Envoi bordereau nominatif
Indice;CHAR(2);Indice appliqué
Echeance;CHAR(2);Echéance de l'indice (MM)
Effectif;CHAR(5);Effectif
CdRegr;CHAR(3);Code regroupement 1
CdGroupe;CHAR(3);Code regroupement 2
Periodicite;CHAR(1);Périodicité
Terme;CHAR(1);Terme
Produit;CHAR(6);Code produit affecté
Inspecteur;CHAR(5);Inspecteur
CleInsp;CHAR(1);Clé inspecteur
Filler;CHAR(6);Filler
4
  • It doesn't make sense to add the flag -i to the command sed and to give the name of a file as argument when you are reading the input from the standard input stream with the operator | in bash. Commented Dec 16, 2021 at 10:41
  • for the moment i do that for one file only but, i'll need to do it for a whole directory of files. that's why Commented Dec 16, 2021 at 10:43
  • 1
    @YoussefHammouma It doesn't matter whether you're operating on one file or many; sed -i doesn't make any sense in a pipeline. The point of a pipeline is to pass the output from one command to the input of another, but sed -i doesn't produce any output, or read any input. You need to either do the edit with a single sed -i command (no pipe, no read, no echo, etc), or make a shell loop over the files (something like for fichier in *.des.txt; do ...) and use sed without the -i (and only pass the file to the first sed command, so the others read from the pipe, not the file). Commented Dec 16, 2021 at 10:52
  • 1
    For #!/bin/bash to do anything useful, the characters # and ! need to be literally the first two bytes of the file. The indentation you show in your question changes this line into just a comment and no longer a valid shebang Commented Dec 16, 2021 at 10:53

2 Answers 2

3

You generally don't want to run sed -i on the same file more than once.

Your entire task can be rephrased into just

sed -i '1s/TABLE/01 /' APGFPOLI.des.txt

If the replacement string should come from a shell variable, you need to use double quotes instead of single:

replacement="05"
sed -i "1s/TABLE/$replacement /" APGFPOLI.des.txt

If you want to keep your other tasks (which are not documented in the question) you can easily merge them into the same script. Remember, sed is a scripting language; you can feed in arbitrarily complex scripts (and some crazy people have even implemented desk calculators and Game of Life in sed scripts).

sed -i -E -e '1 s/TABLE/01 /' -e 's/CHAR/PIC X/' \
          -e '/Numérique/s/;Numérique\s+([^;]*)/;PIC 9(\1)/' APGFPOLI.des.txt

If after this you want to pull out the result and display it with some decorations, I would add a second sed script without -i so that it displays the output on standard output without modifying the file.

sed '1s/\([^;]*\);\([^;]*\);\([^;]*\);.*/* \3\n05 \2 \1/;q'  APGFPOLI.des.txt
Sign up to request clarification or add additional context in comments.

6 Comments

Great, thank you so much. But now with the "echoes" that i put in the shell i have this output : "05 01 APGFPOLI." . Is there a way to echo my first line without the "05" unlike all the other lines ?
I would just run another sed to pull out the first line and add the decorations you want around it to standard output. See updated answer with a rough sketch now (hope I transcribed your fields correctly).
I think that i did full bullsh*t. I saw that sed actually edit my source file. I do not want that, i want to keep my source like that and create a target file with the modifications i did. I am so lost, how can i do that i never tought that sed edit the source file :(
Remove the -i option if you don't want to write the changes back to the input file. Going forward, probably spend more time on explaining your actual requirements.
Ok but why removing the -i option removed the changes in the output file ? Because i removed all the -i so i can keep my original source. But now when i cat my output file there is no changes on it
|
1

For removing TABLE; from the first line and to prepend 01 , you just have to do:

fichier="APGFPOLI.des.txt"
sed -i '1s/^TABLE;/01 /' "$fichier"

When you ask something in SO, it is advisable to remove the part of the code that is not relevant to your problem, like the command sed -i 's/CHAR/PIC X/' $fichier and so on.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.