The comma is separating different items and in each item I want to remove everything between - and : including - but keeping :.

How can I do that? So it should look like:


I used sed 's/-.*://' 1.file > 2.file but ended up removing the whole file and just kept the first and last values.

  • 1
    It looks like your input is a single line, and sed operates a line at a time. Since your regular expression allows for matching .*, the longest (greedy) match is from the first - to the last :. That's why it's deleting everything. You could try replacing the .* with [^,]*, which will force it to stop at the comma between items.
    – Dave M.
    Commented Sep 29, 2017 at 20:51

2 Answers 2


.* is a greedy regexp, matching the longest possible match. You need to match the shortest match but match it globally on the whole line. Try

sed 's/-[^:-]*:/:/g' 1.file > 2.file

The character class [^:-] matches anything except colon and dash (and maybe it should match anything except colon only), so the regexp says "dash followed by any number of non-dash, non-colon characters followed by a colon". It then replaces that with a colon (since you wanted to keep that) and does the replacement globally (the trailing g) on the line. If you omit the g, only the first instance would be replaced.

  • Thanks Nick, I still do not understand why cannot we say directly sed 's/-*:/:/g' why do we need [^:-]? Commented Sep 29, 2017 at 21:26
  • .* will match the longest sequence of characters possible (that's why it's termed "greedy"). So /-.*:/ says "dash followed by any number of characters followed by colon": that matches the first dash and the last colon in your line (and everything in between) because that's longer than any other match. Is that clear?
    – NickD
    Commented Sep 29, 2017 at 21:30
  • Thank you so much! I've tweaked your regex to help me convert a JSON localization file to an iOS localization file. This was so helpful.
    – Felipe
    Commented Mar 19, 2021 at 16:47

Awk solution:

awk -F',' '{ for(i=1;i<=NF;i++) sub(/-[^:-]+/,"",$i) }1' OFS=',' 1.file

  • -F',' - field separator

  • for(i=1;i<=NF;i++) - iterating through all fields of the record

  • sub(/-[^:-]+/,"",$i - substitute the needed sequence (between - and : including - but keeping :)

The output:

  • can you explain the command? Commented Sep 29, 2017 at 21:25
  • @AhmedMagdyMoustafa, see my explanation Commented Sep 29, 2017 at 21:34

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .