2

I have to make a csv-file from a textfile which contains data without any delimiters.

Looks like:

2015021DUMMY001EAN1377689456777678945GERDE0002345
2015031DUMMY002EAN1345647876867867867TURTR0154565
......

Is there an easy way to insert a semicolon every x, y and z characters in every line, preferably using bash or sed?

2
  • 2
    If your system uses GNU coreutils, there's a fairly easy way using cut: cut --output-delimiter=";" -c1-12,13-44,45-60,61- file – steeldriver Dec 31 '15 at 22:27
  • If there is a known maximum to line length, GNU awk if available can do this with something like awk -vFIELDWIDTHS='12 32 16 9999' -vOFS=';' '{$1=$1;print}' file (assigning to any $fld rebuilds the record so $1=$1 is an idiom to rebuild with no change to the data) but that doesn't satisfy your preference for sed. – dave_thompson_085 Jan 1 '16 at 21:37
4

You could use groups of 12, 32 and 16 characters (12+32=44, 44+16=60):

sed 's/\(.\{12\}\)\(.\{32\}\)\(.\{16\}\)/\1;\2;\3/'

Your sample input doesn't contain 60 characters (49, if I got my count right). Otherwise, using just 12 and 32:

$ sed 's/\(.\{12\}\)\(.\{32\}\)/\1;\2;/' input
2015021DUMMY;001EAN1377689456777678945GERDE00;02345
2015031DUMMY;002EAN1345647876867867867TURTR01;54565

... which may or may not be what you wanted.

In general, the groups would be x, y-x and z-y-x characters long.

Or you could use three separate substitutions:

sed 's/.\{12\}/&;/; s/.\{45\}/&;/; s/.\{62\}/&;/'

In this case, the lengths would be x, y+1 (for the semicolon inserted for x) and z+2.

2
sed 's/./&;/59; s//&;/43; s//&;/11' <in >out

I'm not sure if you want the ; to be the twelfth, forty-fourth, or sixtieth character on a line or to follow it. If the latter, either add one to all of those numbers and risk appending a semicolon to the very end of the line (if that matters) or see below. As it is written, above, though, sed won't append a sixtieth char if there isn't already a fifty-ninth.

To do insertions as opposed to appending:

sed 's/./;&/60; s//;&/44; s//;&/12' <in >out

...is another way. In this case sed will never append a semicolon to the tail of the line - semicolons are only inserted at the sixtieth character position (for example) if after doing so there will definitely be a sixty-first.

The three substitutions are not mutually dependent. Either way it is written, sed will add either one, two, or three semicolons to a line depending on its length. Any line with fifty-nine or sixty chars will get three, shorter lines that are at least longer than forty-two or forty-three chars get two semicolons, and other lines matching at least eleven or twelve characters are edited only the once. Lines with fewer than eleven characters are not affected.

If you wanted to only affect lines which were long enough to justify all three semicolons:

sed  -e's/./;&/60;ts'  -eb -e:s \
     -e's//;&/44;s//;&/12' <in >out

...that would work.

...with a GNU sed (and minised) you can Test a substitution for failure rather than only for success as well:

sed -e's/./&;/59;T; s//&;/43; s/&;/12' <in >out

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.