I have a csv file, and I want to delete lines if their 12th character is not ;.

So, for example, my file looks like this:


and I want:


How can I remove a line if the 12th character in it is NOT ; with sed? =)

  • You are asking two different questions here. Do you want to delete lines whose Nth character is not ; or lines whose Nth field is >1 in length? – terdon Mar 17 '16 at 13:21
  • delete lines whose Nth character is not ; - this one) – Konstantin Mar 17 '16 at 13:22
  • Are you sure? If you're working with field-based data, it makes more sense to deal with fields instead of characters. What if one of the lines starts with a space? What if one fo the lines has a longer 1st field than you expect? – terdon Mar 17 '16 at 13:23
  • Yes, I'm pretty sure, but thanks for option =) My file is well aligned and that would be the best case for solution in my opinion =) – Konstantin Mar 17 '16 at 13:24
  • But it is an option actually, depends on which way is easier to declare in sed =) – Konstantin Mar 17 '16 at 13:27

To delete all lines whose 12th character is not ;, you could do:

 $ sed -E '/^.{11}[^;]/d' file

Or, to edit the original file (if your sed supports -i):

$ sed -iE '/^.{11}[^;]/d' file

And if your sed doesn't support -E:

sed -i '/^.\{11\}[^;]/d' file

However, since this is a csv file, it is much safer to use fields instead of character counts. For example, use awk and tell it to print all lines whose 3rd field is one character long:

$ awk -F';' 'length($3)==1' file

With recent GNU awk, you can edit the file in place:

 awk -iinplace -F';' 'length($3)==1' file

This has the advantage of being robust to changes in the lengths of the preceding fields. Unlike the sed approach, it won't fail if you have leading whitespace on a line or if any of the 1st 2 fields are longer (or shorter) than you expect. As a general rule, if your data is field-separated, using the fields is a better idea than using character positions.

| improve this answer | |
  • You have forgot the -i option, to edit the file in place: sed -i -E '/^.{11}[^;]/d' file – Eliad Mar 17 '16 at 14:16
  • sed -i ain't portable to e.g. OpenBSD. – thrig Mar 17 '16 at 14:51
  • @thrig true but most implementations (including FreeBSD, ) do. But OK, I added a disclaimer. – terdon Mar 17 '16 at 14:57
  • can't seem to restrain impulse to upvote every time I see awk -iinplace – iruvar Mar 17 '16 at 15:25

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.