0

I am using this code to search and replace text in all php files in current directory:

for file in `find * -type f -name "*.php"`; do awk 'BEGIN { RS="" } FILENAME==ARGV[1] { s="$0" } FILENAME==ARGV[2] { r="$0" } FILENAME==ARGV[3] { gsub(s,r) ; print }' "zsearch" "zreplace" "$file" > "$file"tmp7 && mv "$file"tmp7 "$file";echo "$file"; done

If contents of zsearch file:

<br>
<center><!--LiveInternet counter--><script type="text/javascript"><!--

it's working great, but if contents of zsearch file:

<!--LiveInternet counter--><script type="text/javascript"><!--
document.write("<a href='http://www.liveinternet.ru/click' "+
"target=_blank><img src='http://counter.yadro.ru/hit?t16.6;r"+
escape(document.referrer)+((typeof(screen)=="undefined")?"":
";s"+screen.width+"*"+screen.height+"*"+(screen.colorDepth?
screen.colorDepth:screen.pixelDepth))+";u"+escape(document.URL)+
";"+Math.random()+
"' alt='' title='LiveInternet: показано число просмотров за 24"+
" часа, посетителей за 24 часа и за сегодня' "+
"border=0 width=88 height=31></a>")//--></script><!--/LiveInternet-->

it's not working, not replacing

I think it's due to parenthesis ( symbol in document.write("

Maybe I need to escape other symbols like + or *?

kostya572
  • 169
  • 2
  • 21

1 Answers1

1

Your main issue is using regexps instead of strings, try this (also improved your file loop):

find * -type f -name "*.php" |
while IFS= read -r file; do
    awk '
        BEGIN { RS="" }
        FILENAME==ARGV[1] { old=$0 }
        FILENAME==ARGV[2] { new=$0 }
        FILENAME==ARGV[3] {
            if ( start = index($0,old) ) {
                $0 = substr($0,1,start-1) new substr($0,start+length(old))
            }
            print
        }
    ' "zsearch" "zreplace" "$file" > "$file"tmp7 &&
    mv "$file"tmp7 "$file"
    echo "$file"
done

It'll still fail for files that have newlines in their names - if that's a possibility for you let us know.

Ed Morton
  • 188,023
  • 17
  • 78
  • 185
  • Thank you for the answer, I've tested the code and it's not working, it nothing changes, tried for a small portion of text to replace from "" to "replacedtext". Maybe there some typo with "substr" in code? I want to search and replace text or code in a convenient way by simply copy-pasting text or code without difficult regexp rules. – kostya572 Sep 01 '17 at 00:08
  • There is no regexp in my code, it's a simple string substitution, I don't see any issues with the code but obviously I can't test it since your question doesn't include sample input/output I can test with. Oh hang on - it's the quotes around `$0`. Your code has `s="$0"` instead of `s=$0` and I just copied that without thinking about it. Fixing that now... – Ed Morton Sep 01 '17 at 00:51
  • 1
    Wow, everything works great now! Quotes changed everything, you helped me a lot. I've seen the similar solution with sed, but I like more awk solution with external files. – kostya572 Sep 01 '17 at 01:00
  • 1
    Great, glad to hear it. There is no similar solution in sed because, unlike awk which has string functions, sed **cannot** work with literal strings - it uses regexps in the search field and backreference-enabled strings in the replacement field so you have a WHOLE lot of escaping to do to try to make sed act as if it were working with strings in the search and replacement parts - see https://stackoverflow.com/a/29626460/1745001. – Ed Morton Sep 01 '17 at 01:02
  • Found that script not always "substr" correct start position, if "zsearch" text file starts with "<", it can replace it like double "<<". Found that "-1" can help in code "substr($0,1,start-1)", but that not works with simple alphabetical characters. Is there something that can detect special non-alphabetical or multi-byte characters? Sorry for troubling. – kostya572 Sep 01 '17 at 10:40
  • Yeah it should always be start-1, fixed that. I believe gawk supports multibyte characters based on your locale setting but you'd have to look at the gawk man page for details. – Ed Morton Sep 01 '17 at 11:46