macosawk

How to create multiple files from a single file using separators?


I am trying to generate multiple files from a .txt file with separators. In this case, the column separator is | and the record separator is: .

Each name value only appear once in the input.

This is the code I'm trying:

awk -F'║', -vOFS=, -vc=1 '
NR == 1 {
    for (i=1; i<NF; i++) {
        if ($i != "") {
            g[c]=i;
            f[c++]=$i
        }
    }
}
NR>2 {
    for (i=1; i < c; i++) {
        print $1,$2, $g[i] > "output_"f[i]".tex"
    }
}' biennalis.txt

The content of biennalis.txt is something like this:

name|content
║Is-id27-ref06-01-13-1914|El año de la muerte del rey Ozías vi al Señor sentado en un trono excelso y elevado, y sus haldas llenaban el templo. Unos serafines se mantenían erguidos por encima de él; cada uno tenía seis alas: con un par se cubrían la faz, con otro par se cubrían los pies, y con el otro par aleteaban, y se gritaban el uno al otro:

 \textquote{Santo, santo, santo, el Señor de los ejércitos: llena está toda la tierra de su gloria.}.

 Se conmovieron los quicios y los dinteles a la voz de los que clamaban, y la casa se llenó de humo.

 Yo dije:

 \textquote{¡Ay de mí, que estoy perdido, pues soy un hombre de labios impuros, y entre un pueblo de labios impuros habito: que al rey el Señor de los ejércitos han visto mis ojos!}

 Entonces voló hacia mí uno de los serafines con una brasa en la mano, que con las tenazas había tomado de sobre el altar, y tocó mi boca y dijo:

 \textquote{He aquí que esto ha tocado tus labios: se ha retirado tu culpa, tu pecado está expiado.}

 Y percibí la voz del Señor que decía:

 \textquote{¿A quién enviaré? ¿y quién irá de parte nuestra}?

 Yo contesté:

 \textquote{Heme aquí: envíame.}

 Dijo:

 \textquote{Ve y di a ese pueblo: \textquote{Escuchad bien, pero no entendáis, ved bien, pero no comprendáis.} Engorda el corazón de ese pueblo, hazle duro de oídos, y pégale los ojos, no sea que vea con sus ojos y oiga con sus oídos, y entienda con su corazón, y se convierta y se le cure.}

 Yo pregunté:

 \textquote{¿Hasta dónde, Señor?}

 Y él me contestó:

 \textquote{Hasta que se vacíen las ciudades y queden sin habitantes, las casas sin hombres, la campiña desolada, y haya alejado el Señor a las gentes, y cunda el abandono dentro del país. Aun el décimo que quede en él volverá a ser devastado como la encina o el roble, en cuya tala queda un tocón. Este tocón será semilla santa.}


║Is-id27-ref01-01-18-0045|Visión de Isaías, hijo de Amós, acerca de Judá y de Jerusalén, en tiempos de Ozías, Jotán, Ajaz y Ezequías, reyes de Judá.

 Oíd, cielos, escucha tierra, que habla el Señor: \textquote{Hijos he criado y educado, y ellos se han rebelado contra mí.

 El buey conoce a su amo, y el asno el pesebre de su dueño; Israel no me conoce, mi pueblo no comprende}.

 ¡Ay, gente pecadora, pueblo cargado de culpas, raza malvada, hijos corrompidos! Han abandonado al Señor, han despreciado al santo de Israel, le han vuelto la espalda.

The end result I expect is separate files, whose name is the content of the first column and the content is what is in the second column:

Is-id27-ref06-01-13-1914.tex

El año de la muerte del rey Ozías vi al Señor sentado en un trono excelso y elevado, y sus haldas llenaban el templo. Unos serafines se mantenían erguidos por encima de él; cada uno tenía seis alas: con un par se cubrían la faz, con otro par se cubrían los pies, y con el otro par aleteaban, y se gritaban el uno al otro:

 \textquote{Santo, santo, santo, el Señor de los ejércitos: llena está toda la tierra de su gloria.}.

...

Is-id27-ref01-01-18-0045.tex

Visión de Isaías, hijo de Amós, acerca de Judá y de Jerusalén, en tiempos de Ozías, Jotán, Ajaz y Ezequías, reyes de Judá.

 Oíd, cielos, escucha tierra, que habla el Señor: \textquote{Hijos he criado y educado, y ellos se han rebelado contra mí.

...

Etc ...

The error when executing the command is as follows:

awk: syntax error at source line 10
    context is
        print $1,$2, $g[i] > >>>  "output_"f <<< [i]".tex"
awk: illegal statement at source line 10

Solution

  • Your script appears to be doing something quite different than what you are attempting. Assuming that the actual input file is well-formatted, let's ditch what you had and try again.

    awk 'FNR==1 { next }
      /[║|]/ { split($0, n, /║/);
        if(f) { print n[1] >>f; close(f) }
        split(n[2], m, /\|/);
        f = "output_" m[1] ".tex"; print m[2] >>f; next }
    f { print >>f; next }
    { print "orphan input: " $0 }' biennalis.csv
    

    This splits any line with or | in it, and uses the first field as the base of the new file name. It takes anything before and appends that to the previously open file if there was one, so the delimiter can occur anywhere in a line; but this will break in peculiar ways if a line contains more than one of each delimiter.

    This crucially assumes that you have a before the first entry and | between the file name and the text you want in that file.

    Demo: https://ideone.com/jsRJKf


    My original answer works fine on Linux, but not on MacOS:

    awk 'BEGIN { RS="║"; FS="|" }
      FNR > 1 { o = "output_" $1 ".tex"; print $2 >>o; close(o) }' biennalis.csv
    

    We simply instruct Awk to use the proper record and field separators, and then instruct it to print the second field to a file whose name is derived from the first.

    As above, for this to work, you have to have a before the first entry and | between the file name and the text you want in that file.

    Demo: https://ideone.com/LU1y4Y