1

I would like some advice on this script.
I'm trying to use sed (I didn't manage it with rename) to change a file that contains lines of the format (my test file name is sedtest):

COPY W:\Interfaces\Payments\Tameia\Unprocessed\X151008\E*.*

(that's not the only content of the file).

My goal is to replace the 151008 date part with a different date, I've tried to come up with a solution in sed using this:

sed -i -e "s/Unprocessed\X.*/Unprocessed\X'BLABLA'/" sedtest

but it doesnt seem to work, the line remains unchanged, it's like it doesn't recognize the pattern because of the \. I've tried some alternative delimiters like #, but to no avail.

Thanks in advance for any advice.

Armali
  • 18,255
  • 14
  • 57
  • 171
onlyf
  • 767
  • 3
  • 19
  • 39
  • 1
    Sed (like many unix tools) uses backslashes to change the "specialness" of the following character. To change the specialness of the backslash itself, put a backslash in front of it. – ghoti Oct 15 '15 at 11:48

1 Answers1

2

There's a couple of issues with your sed command. I would suggest changing it to this:

sed -r 's/(Unprocessed\\X)[0-9]+/\1BLABLA/' file

Since your version of sed supports -i without requiring that you add a suffix to create a backup file, I assume you're using the GNU version, which also supports extended regular expressions with the -r switch. The command captures the part within the () and uses it in the replacement \1. Don't forget that backslashes must be escaped.

If you're going to use -i, I would recommend doing so like -i.bak, so a backup of your file is made to file.bak before it is overwritten.

You haven't shown the exact output you were looking for but I assumed that you wanted the line to become:

COPY W:\Interfaces\Payments\Tameia\Unprocessed\XBLABLA\E*.*

Remember that * is greedy, so .* would match everything up to the end of the line. That's why I changed it to [0-9]+, so that only the digits were replaced, leaving the rest of the line intact.


As you've mentioned using a variable in the replacement, you should use something like this:

sed -r -i.bak "s/(Unprocessed\\X)[0-9]+/\1$var/" file

This assumes that $var is safe to use, i.e. doesn't contain characters that will be interpreted by sed, like \, / or &. See this question for details on handling such cases reliably.

Community
  • 1
  • 1
Tom Fenech
  • 72,334
  • 12
  • 107
  • 141
  • 1
    For reference, FreeBSD and OSX also support ERE with the `-E` switch, and for the last couple of years FreeBSD has also permitteed `-r` for compatibility with GNU sed. Excellent point regarding `-i`. Plusone. – ghoti Oct 15 '15 at 12:05
  • First of all, thank you very much. This works and outputs it into the screen, but the file in question remains unchanged.. – onlyf Oct 15 '15 at 12:20
  • and yes, that's the exact output i m going for, there's an environmental variable that ll go into that BLABLA – onlyf Oct 15 '15 at 12:22
  • @onlyf that's because I removed the `-i` switch. You can put it back in to edit the original file (taking into account the advice in my answer regarding backups). – Tom Fenech Oct 15 '15 at 12:23
  • which also doesnt work, i tried to replace BLABLA with $var, it didnt return the value (Sorry, i m really new to sed) – onlyf Oct 15 '15 at 12:24
  • i.bak is great, i didnt know about it. :) I had made an entire script to backup those files separetely and it turns out i dont need it. You saved me so much time man. – onlyf Oct 15 '15 at 12:26
  • @onlyf if you're planning on using a shell variable in the replacement you'll need to use double quotes around the command. Also, take care if your replacement contains any special characters (there are plenty of other answers that deal with how to do this safely). – Tom Fenech Oct 15 '15 at 12:26
  • tede@cobolinuxdeb:~/n55115/PD$ sed -r -i -e "s/(Unprocessed\\X)[0-9]+/\1$btchdt/" sedtest tede@cobolinuxdeb:~/n55115/PD$ cat sedtest COPY W:\Interfaces\Payments\Tameia\Unprocessed\X"$btchdt"\E*.* – onlyf Oct 15 '15 at 12:28
  • Looks like you already made the replacement with single quotes around the command...I'd make use of that backup and try again! – Tom Fenech Oct 15 '15 at 12:32
  • I have a question, and maybe it just doesnt click into me but...this seems odd to me. First of all $a doesnt work, with single or double quotes, secondly when i redo the sed, with a different string, it doesnt change anything anymore. Could you help me get it? – onlyf Oct 15 '15 at 12:44
  • tede@cobolinuxdeb:~/n55115/PD$ nano sedtest tede@cobolinuxdeb:~/n55115/PD$ sed -r -i 's/(Unprocessed\\X)[0-9]+/\1lalala/' sedtest tede@cobolinuxdeb:~/n55115/PD$ cat sedtest COPY W:\Interfaces\Payments\Tameia\Unprocessed\Xlalala\E*.* tede@cobolinuxdeb:~/n55115/PD$ sed -r -i 's/(Unprocessed\\X)[0-9]+/\1rororo/' sedtest tede@cobolinuxdeb:~/n55115/PD$ cat sedtest COPY W:\Interfaces\Payments\Tameia\Unprocessed\Xlalala\E*.* tede@cobolinuxdeb:~/n55115/PD$ – onlyf Oct 15 '15 at 12:45
  • >tede@cobolinuxdeb:~/n55115/PD$ nano sedtest >tede@cobolinuxdeb:~/n55115/PD$ sed -r -i 's/(Unprocessed\\X)[0-9]+/\1lalala/' sedtest >tede@cobolinuxdeb:~/n55115/PD$ cat sedtest COPY W:\Interfaces\Payments\Tameia\Unprocessed\Xlalala\E*.* >tede@cobolinuxdeb:~/n55115/PD$ sed -r -i 's/(Unprocessed\\X)[0-9]+/\1rororo/' sedtest >tede@cobolinuxdeb:~/n55115/PD$ cat sedtest COPY W:\Interfaces\Payments\Tameia\Unprocessed\Xlalala\E*.* >tede@cobolinuxdeb:~/n55115/PD$ – onlyf Oct 15 '15 at 12:46
  • I think for some reason my system does not recognize the "-" characters in this, it doesnt even do standard changes when i bracket the entire expression in "'s, let alone call on the value of a variable.. – onlyf Oct 15 '15 at 13:00
  • 1
    I edited my answer to show how to use a variable in the replacement string, linking to a question which deals with more complex cases. I'm afraid that this is getting beyond the scope of your original question. Some general pointers: don't use `-i` when debugging your sed command, use `set -x` to see exactly what command is being run and don't dump shell commands / output in the comments here, it's totally unreadable. Good luck. – Tom Fenech Oct 15 '15 at 13:05