SED assistance: add character in the middle of a string.
I resolved the problem after trying in vain to make sed work as I wanted it to, but my problem was this:
I have a folder of MP3s, where some have <artist>- <song> and others have <artist> - <song>. I wanted to make all of them say <artist> - <song> The command that works for me was for i in *[a-Z]-*; do mv "$i" "`echo $i | sed 's/-/ -/g'`"; done but if I -hadn't- used ls with my parameters to filter out the valid results, how would I have done this with sed? I got close with: ls | sed -e 's/\(.*\)[a-Z]-\(.*\)/\1 - \2/' but with the above I lose the [a-Z] character that I used to match with (and I need to keep that). My basic question is what I needed to do with the above command to make it work as expected within sed (again, I've since solved it, I'm just trying to understand sed bettter)? Thanks in advance for your time and responses =) |
Hi,
[a-Z] is not a legal range, although sometimes accepted. Sed does not accept it. You do mention that you need/want to keep the [a-Z] part, which would limit your options considerably!! Why not something like this: ls | sed 's/[[:blank:]]*-[[:blank:]]*/ - /g' This looks for a dash (-) that has zero or more blanks in front and after it and changes this into a space a dash and a space (globally). I intentionally used [:blank:] to include all blanks and not just a space. Hope this helps. |
You simply need to make sure that every character you want to save is inside back-referenced parentheses. In this case, just expand the first set to included the a-Z reference.
It's also easier when dealing with regex to use the -r option. That way you don't have to backslash-escape everything. Code:
ls | sed -r -e 's/(.*[[:alnum:]])- (.*)/\1 - \2/' Something like this would be even better. It can be run on both correct and incorrect names, as long as there's a space after the hyphen in the middle. Code:
ls |sed -r -e 's/([^- ]+)- (.*)/\1 - \2/' Finally, instead of using sed, ls, and/or loops, I recommend perl rename, a convenient renaming script included in some distro's perl implementations. It uses the same general sed/perl syntax as above and works with standard shell file globbing. A stand-alone version is available here: http://tips.webdesign10.com/files/rename.pl.txt |
Thanks to both of you for your responses. I didn't realize I could use blank like that and wasn't aware of the -r flag, which will certainly make things easier going forward :)
I'll check out the perl mention, but I think the closest answer to the method I was using is: Code:
ls |sed -r -e 's/([^- ]+)- (.*)/\1 - \2/' Quote:
Thanks again, I'll add some reputation as soon as I figure out how to do it XD |
Good catch. No, you don't really need the plus sign there. I put it in out of habit because that pattern is often used to stop a regex pattern from being greedy.
When ^ is at the first position inside brackets it negates the character range, so [^- ] means to match anything that's not a hyphen or a space. For that matter, you'd probably really only need to negate the space here ([^ ]). It really depends on how careful you need to be in weeding out false matches. You could even use a really simplified version like this if there's no chance of there being multiple not-space+hyphen+space combinations. Code:
ls | sed -r 's/([^ ])- /\1 - /' |
All times are GMT -5. The time now is 05:07 AM. |