replace 1.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859
  1. #!/bin/sh
  2. usage () {
  3. cat <<EOF>&2
  4. Usage: ${0##*/} [OPTIONS] SEARCH REPLACE [FILES]
  5. Replace SEARCH by REPLACE in FILES. If no file is provided, use stdin.
  6. Backslashes are interpreted in SEARCH and REPLACE (e.g. \n, \t). If you want to
  7. inhibit this behaviour, you need to double them.
  8. Options:
  9. -h: Show this help.
  10. -i: Replace file content instead of printing to stdout.
  11. EOF
  12. }
  13. OPT_INPLACE=""
  14. while getopts ":ih" opt; do
  15. case $opt in
  16. i)
  17. OPT_INPLACE=-i ;;
  18. h)
  19. usage
  20. exit 1 ;;
  21. \?)
  22. usage
  23. exit 1 ;;
  24. esac
  25. done
  26. shift $((OPTIND - 1))
  27. if [ $# -lt 2 ]; then
  28. usage
  29. exit 1
  30. fi
  31. search="$1"
  32. replace="$2"
  33. shift 2
  34. replace () {
  35. ## We cannot use gsub, otherwise regex substitutions could occur.
  36. ## Source: http://mywiki.wooledge.org/BashFAQ/021
  37. awk -v s="$search" -v r="$replace" 'BEGIN {l=length(s)} {o="";while (i=index($0, s)) {o=o substr($0,1,i-1) r; $0=substr($0,i+l)} print o $0}' "$@"
  38. }
  39. if [ $# -eq 0 ] || [ -z "$OPT_INPLACE" ]; then
  40. replace "$@"
  41. else
  42. for i ; do
  43. out="$(mktemp "$i.XXXXXX")"
  44. replace "$i" > "$out"
  45. mv "$out" "$i"
  46. done
  47. fi