I'm trying to find and replace in a file:

echo "$BRANCH_NAME" >> "$WORKING_DIR"/test.text
    sed -i '' "remote_paths/.*[\/]([^\"]*)/$BRANCH_NAME/g" "$WORKING_DIR"/sftp-config.json

... the script successfully creates test.text and prints the BRANCH_NAME so I know its working good so far. However I can't get the find and replace working.

The regex output is, in case you're wondering:

Full match  `remote_path": "/home/myname/public_html/ABC-1271`
Group 1.    `ABC-1271`

In simple terms, this is what I'm trying to achieve:

Find ABC-1271 in string remote_path": "/home/myname/public_html/ABC-1271 of file sftp-config.json and replace ABC-1271 with XYZ-1225 ($BRANCH_NAME)

closed as unclear what you're asking by G-Man, Anthon, steve, Rui F Ribeiro, DarkHeart May 2 '17 at 11:43

Please clarify your specific problem or add additional details to highlight exactly what you need. As it's currently written, it’s hard to tell exactly what you're asking. See the How to Ask page for help clarifying this question. If this question can be reworded to fit the rules in the help center, please edit the question.

  • (1) What is in the sftp-config.json input file?  (2) What is the value of $BRANCH_NAME?  (3) Please describe in sentences (English sentences constructed of English words) what you want this sed command to do.  (4) What do you mean by “The regex output”? Do you mean the output from sed?  (5) It’s good practice to debug your sed commands without the -i option, and then add it when the text manipulation functionality is working.  (6) Why are you searching for remote_paths when your file contains remote_path? – G-Man May 1 '17 at 6:31
  • @G-Man (1) It contains the sFTP info including the remote_path, this script is a git hook that changed the path on switching the branch (2) its the working directory name, for example XYZ-1225 (3) find ABC-1271 in remote_path": "/home/myname/public_html/ABC-1271 in the file sftp-config.json and replace ABC-1271 with XYZ-1225 (4) No the result if I run regex on sftp-config.json (5) Ah ok (6) To find and replace – 3zzy May 1 '17 at 6:37
  • 2

Your sed command is a bit messed up.

sed -i '' "remote_paths/.*[\/]([^\"]*)/$BRANCH_NAME/g"

First of all, don't use sed with -i if you're still trying to get thing to work. That's just a recipe for destroying important files.

Secondly, the r in remote_path is a sed command that reads a file. I'm pretty sure it looks for a file called emote_paths/.*[\/]([^\"]*)/$BRANCH_NAME/g or at least emote_paths. In either case, it won't exit with an error if the file does not exist.

It looks like you'd wanted something like


The command becomes

sed "s#\(remote_path.*/home/myname/public_html/\)\([A-Z0-9-]*\)#\1$BRANCH_NAME#g" \
  "$WORKING_DIR/sftp-config.json" >"$WORKING_DIR/sftp-config.json.new"

Or, if the branch name is the last thing on the line after the last / and the string remote_path uniquely locates this line:

sed "/remote_path/s#/[^/]*\$#$BRANCH_NAME#" \
  "$WORKING_DIR/sftp-config.json" >"$WORKING_DIR/sftp-config.json.new"

Ideally, though, you'd be using a JSON-aware tool for doing this, for example jq:

jq ".remote_path = (.remote_path | split(\"/\") | .[-1] = \"$BRANCH_NAME\" | join(\"/\"))" \
  input.json >output.json
  • @3zzy if that's a clarification to your question please edit your question and put it there where it's easy for everyone to find. Updates in comments can easily get overlooked. – roaima May 1 '17 at 6:45
  • Yes, just updated the description – 3zzy May 1 '17 at 6:52
  • @Philippos The '' is an argument to the -i flag. It's modifying the file in-place. – Kusalananda May 1 '17 at 7:06
  • Oh, thank you! Seems I'm too much used to gnu sed with no arguments for -i. Sorry. – Philippos May 1 '17 at 7:09
  • @Kusalananda This is what the sftp-config looks like: pastebin.com/SqTzd2sQ – 3zzy May 1 '17 at 7:12

(1) remote_path seems to be an address, filtering the line with that pattern? Then surround it by slashes: /remote_path/

(2) You seem to create an expression for the whole line, but only want to replace the part you marked with (). Right? But they are used very differently (grouping or back references) and you'd need to escape them \(\)or use option -E for extended regular expressions

(3) Find a pattern that matches only the branch name to be replaced like a dash between uppercase letters and numbers: [A-Z]*-[0-9]*

We end up with

sed -i '' "/remote_path/s/[A-Z]*-[0-9]*)/$BRANCH_NAME/g" "$WORKING_DIR"/sftp-config.json

And try it without the -i option first

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