Link to home
Start Free TrialLog in
Avatar of phoffric
phoffric

asked on

Unable to define alias to allow sed to handle escaped space

I haven't worked in bash for many years. Someone at work had a problem with substituting a string in a file with a string that included a space. Here is what is in the .bashrc file.
alias frf='set -o noglob;_frf'

function _frf
{
    \echo “Replacing $1 with $2 in all $3 files…”
    \grep -li $1 $3 | \xargs -tI@ \sed -i 's/'$1'/'$2'/g' @
    return
}

Open in new window

The files 1.txt and 2.txt are identical with the contents:
this is a string

Open in new window

The following gives no problems:
frf ring rung
frf rung ring
Then diff 1.txt 2.txt shows no differences.

But the following gives an error:
$ frf ring "r\ ing" 1.txt
“Replace ring with r\ ing in all 1.txt files…”
sed -i s/ring/r\ ing/g 1.txt 
sed: -e expression #1, char 9: unterminated `s' command

Open in new window

I have a couple questions about his alias file.
what does this mean: set -o noglob ?
Why are there '\' before the echo and the grep ?
How to modify this alias to enable escaped spaces?

Btw, what is wrong with diff *.txt which gives error "missing operand after '*.txt'" ? Never had problems like this before. diff 1.txt 2.txt is ok.

I also tried this line which was worse:
find . -name "$3" -exec sed -i 's/$1/$2/g' {} \;

Open in new window

ASKER CERTIFIED SOLUTION
Avatar of arnold
arnold
Flag of United States of America image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of phoffric
phoffric

ASKER

Let's forget about diff *.txt because it is working now. (I only had 1.txt and 2.txt in the folder, so *.txt would expand into those two files. Not sure what the heck was going on with that, unless I was inadvertently in a different folder.)

Here is the clarification:
Let's say the command is to change all the .txt files from:
Nowis the time.
to
Now is the time.
We need a space between the w and the i. How should the function be changed and/or the command line be written to accomplish this.
Your quoting requires a minor change...

's/'$1'/'$2'/g'

Open in new window


to...

"s/'$1'/'$2'/g"

Open in new window


Remember, in wrapping a variable in single quotes means the variable is never expanded, so with your function your actually changing $1 to $2, rather than the value of $1 to $2.
you would search for Nowis and replace it with Now is
frf "Nowis" "Now is" <list of files by pattern>
frf 'Nowis' 'Now is'
$1 will have Nowis
$2 will have Now is
and will not conflict with the match pattern.
When there is a space, you have to encase it you can use single quotes as well.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Why are there '\' before the echo and the grep ?
I have no idea. They achieve nothing at all. Perhaps the original author was under some misconception that they were required, as per arnold's erroneous answer
Without the escape character, echo would be run by bash during the definition of the _frf function such that when the alias was used, no matter the input it would return the same thing.
Here's a test. You can see everything works as before without backslashes:
function _frf
{
    echo "Replacing $1 with $2 in all $3 files..."
    grep -li $1 $3 | xargs -tI@ sed -i 's/'$1'/'$2'/g' @
    return
}
type _frf
_frf is a function
_frf () 
{ 
    echo "Replacing $1 with $2 in all $3 files...";
    grep -li $1 $3 | xargs -tI@ sed -i 's/'$1'/'$2'/g' @;
    return
}
alias frf='set -o noglob;_frf'
type frf
frf is aliased to `set -o noglob;_frf'
cat 1.txt
this is a string
frf ring rung 1.txt
Replacing ring with rung in all 1.txt files...
sed -i s/ring/rung/g 1.txt 
cat 1.txt
this is a strung

Open in new window

(Continued next post)
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I see Duncan has provided a lengthy post and will take another night to digest due to at least 3 home computer problems; two PC's are unusable, but I found another one yesterday; but it too became unusable. My VmWare would not start - just a dark screen for 30 minutes. I uninstalled it and am installing VirtualBox at the moment.

@David, re:
"s/'$1'/'$2'/g"

Open in new window

I am currently not able to test this at home on VIrtualBox. But I tried it at work on RHEL using ksh. (I am currently on an extremely old program, so I guess that is why they use ksh.) Bottom line is that I had no luck with that change. In any case, this question is for bash. If it does not translate to ksh, I'll ask a separate ksh question.

@Arnold, I appreciate your providing the tip. But take a look at the OP, and you and notice that I attempted to add a space with the following cmd line:
$ frf ring "r\ ing" 1.txt

Open in new window


In previous post, I wrote:
Let's forget about diff *.txt because it is working now. (I only had 1.txt and 2.txt in the folder, so *.txt would expand into those two files. Not sure what the heck was going on with that, unless I was inadvertently in a different folder.)
Well, while trying out Arnold's change, I found out that sometimes diff *.txt worked and sometimes it didn't. And with some experimentation, I see it is related to set -o noglob. Now, as I was searching for my glob reference, I found that Duncan has extensive references to this topic, which I will eagerly read. (What baffles me is how did I ever get along without ever using glob when I had to define bash alias functions.)

Thank you for all your inputs. I am going back to my Centos 7 installation on VirtualBox, and will resume this discussion tomorrow.

Regards!!!
Paul
$1 is the first argument in the frf, similarly $2 is the second.

When using quotes, IMHO, you do not need to include an escape.

What happens if you run
frf 'Nowis' 'Now is' testfile.txt

Use cat -v textfile.txt
To expose if any control characters are....
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I'll print this out at work tomorrow. Thanks again!
@David,
fyi - My coworker who asked for help on this problem said he has no problem inserting spaces with sed on the command line, but when putting the function in his alias file and running the function, then he has problems. I wonder whether you tested your remarks on the command line like he did rather than running an alias with the function defined in the alias file. As far as the \echo, etc. question, by any chance, is this a korn shell feature? Re: your explanation on \echo, do you happen to have any bash or ksh documentation to elaborate on this topic?
Thanks,
Paul

p.s. - I am at work, and if I find time between runs, I will look at these posts. There is always this Thursday when I have a whole day off.
Could you post the command the person used to make these changes?
I can not determine what might be an issue without seeing what was executed.
re: \echo
In my ksh window, if I type:
alias echo='ls -l'
echo 1.txt
\echo 1.txt

Open in new window

I get different results. How about you? I think this is what Arnold was telling us (an example would have helped).
Here is an online bash tester: https://repl.it/languages/bash
I get the expected different results there as well. Here are the results:
total 4-rw-r--r-- 1 runner runner 48 Nov 26 22:08 main.sh
ls: cannot access '1.txt': No such file or directory
1.txt

Open in new window

Good pickup! The backslashes in the function definition are there to stop the function picking up aliases when it runs. This behaviour is common to bash & ksh functions - I just tried it.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
How many files meet the pattern you are providing in $3

This is passed as @ array in the alias.

If there are many files, it might exceed the single life length resulting in an error.
These are the diffs from the OP:
*** 2,8 ****
  
  function _frf
  {
      \echo "Replacing $1 with $2 in all $3 files..."
!     \grep -li $1 $3 | \xargs -tI@ \sed -i 's/'$1'/'$2'/g' @
!     return
  }
--- 2,8 ----
  
  function _frf
  {
+     \set +f
      \echo "Replacing $1 with $2 in all $3 files..."
!     \grep -li $1 $3 | \xargs -tI@ sh -c "sed -i 's/'$1'/'\"$2\"'/g' @"
  }

Open in new window

I removed the trailing return (not necessary, and anyway should have a backslash:)
I inserted (backslashed) set +f as discussed previously.
And finally I made xargs run sed via sh -c, and jiggered the quoting a bit.
This tkdiff  tkdiff.pdf  shows visually how few characters are  actually changed.
Seems we are trying to solve a prior use of an alias without

IMHO,

 A command line find and replace with a backup of the file whose contents are changed

Test the following
perl -pi.bak -e 's/oldpattern/newpattern/g;' *

sed -I.bak 's/oldpattern/newpattern/g' *

The expose $3 in the grep could run into issue when there is a file with a space, placing $3 in double quotes may help.
@arnold: what @ array? The only @ I can see is the xargs -I replace-str
The real story with sed and frf ring "r\ ing"
In a previous post which I have now edited, I wrongly stated
backslash ... doesn't mean anything special to sed (some backslash sequences mean a lot to sed, but not backslash-space)
What really happens is that xargs doesn't treat the backslash specially. It sees a space so starts a new argument. You can see this from strace:
execve("/usr/bin/sed", ["sed", "-i", "s/ring/r\\", "ing/g", "1.txt"], [/* 73 vars */]) = 0

Open in new window

Misread regarding @ array.

While you posted $3 in quotes in the most recent post within the grep -li $1 $3 is not
@arnold yes I quoted $2. You would quote $3 on invocation if the file name has spaces but quoting otherwise would stop wildcard expansion would it not?
much of the complexity in answering ..
I do not believe adding "*.txt" will prevent expansion on the command line
The point I was making dealt with $3 in quotes "$3" within the defined alias
In the portion grep -li "$1" "$3"

Problem with file names when populated through bash expansion
A filename data.txt
In $3 will be treated as two files
Filename
Data.txt

With quotes when there are more than one file matched.

It is likely when the alias was created/defined naming conventioneers stayed away from using spaces.

Since the question was posed, different comments solve one issue but might have other issue ..

It might be simpler if the whole thing is made clear what the person wants to achieve
Without trying to untangle the prior use of the frf alias
Hey, just wanted to let you know that as of around 6pm EST, my co-worker said "Thank you!!" and that "you guys are really smart". (And looking at all the ksh scripts he wrote over the years, I think he is pretty advanced himself.) So, I will be closing this issue as soon as I read through it all and try to learn from it.

You have been great help.

BTW, I noticed a perl line commented out in his script - not sure if he had that working, and just got stumped with the sed version of this problem. His only change to Duncan's post (from a few hours ago) was to add something to undo a change. That is, suppose he changes ring to r ung; and then realizes that was a mistake. With his change, he can now undo this by changing r ung to ring. Apparently, it was a small tweak.

(I'll let you know when I get his change - with Thanksgiving, it may be next week. Or, if you are up for the challenge - I now realize this was a hard question, feel free to post your version, and we'll compare notes.)

Oh, he then told me he can't replace string with "string" (i.e., include the double quotes). I told him, one thing at a time. I can ask another question on that, or maybe I'll learn enough this weekend to figure that challenge out myself. He wants the world - to be able to add/remove spaces, to add (and probably to remove) double quotes. But this question was very narrow so I won't be holding up closure on his wish list. Maybe he'll learn from your posts and we'll figure out the rest ourselves.

I just got VirtualBox working with guest additions. Hope it stays up a little longer than the VmWare that I had to uninstall this week.

Thanks again! And for anyone from the USA, have a Happy Thanksgiving!

Best Regards,
Paul
Playing with my new virtual box.
>> I do not believe adding "*.txt" will prevent expansion on the command line
I may be taking this out of context since I haven't read all the posts. But following shows expansion and non-expansion of wildcards based on this globbing thingy.
[admin@localhost ~]$ set -o noglob
[admin@localhost ~]$ ll *
ls: cannot access *: No such file or directory
[admin@localhost ~]$ set -o glob
bash: set: glob: invalid option name
[admin@localhost ~]$ ll
total 0
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Desktop
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Documents
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Downloads
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Music
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Pictures
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Public
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Templates
drwxr-xr-x. 2 admin admin 6 Nov 25 23:32 Videos

Open in new window

Well, I don't know what is wrong with
$ set -o glob
bash: set: glob: invalid option name

but it seemed to get the ll working again so I guess I am happy.

The crazy work environment I'm in (for me) is having the cmd line in vi, and then when running a function with these glob usages, the cmd line changes its form dramatically - I never know what to expect next. (i'll figure it out and customize it to my liking. I just copied alias and environment variables when I started this project from others, and its a hodgepod of different approaches.)
@arnold,
>> Could you post the command the person used to make these changes?
>> I can not determine what might be an issue without seeing what was executed.
Not sure if we are on the same page - what changes are you referring to?
The issue in the OP is the error:
$ frf ring "r\ ing" 1.txt
“Replace ring with r\ ing in all 1.txt files…”
sed -i s/ring/r\ ing/g 1.txt
sed: -e expression #1, char 9: unterminated `s' command
You need to enclose the ..

sed -I.bak 's/ring/r ing/g' 1.txt
Once ran, you will have a 1.txt.bak file as a backup.
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Thanks for this great discussion and experimentation! I am learning a lot! :) When I showed these posts to my coworker who has been writing ksh scripts for over a decade, he only took 5 minutes to absorb everything. I've been at this for hours, and am half way through the posts while experimenting with the scripts.

@arnold wrote a question for me, and I tried the suggestion. Below is my result showing that I needed to escape the space.
When using quotes, IMHO, you do not need to include an escape.
What happens if you run
frf 'Nowis' 'Now is' testfile.txt
Ok, I checked your suggestion out, but as you can see below, I did not get the desired results.
$ type _frf
_frf is a function
_frf () 
{ 
    set +f;
    echo "Replacing $1 with $2 in all $3 files...";
    grep --color=auto -li $1 $3 | xargs -tI@ sh -c "sed -i 's/'$1'/'$2'/g' @"
}
$ ls *.txt
1.txt  2.txt
$ cat *.txt
this is a string
this is a string
$ _frf ring "r ing" "*.txt"
Replacing ring with r ing in all *.txt files...
sh -c sed -i 's/'ring'/'r ing'/g' 1.txt 
sed: -e expression #1, char 8: unterminated `s' command
sh -c sed -i 's/'ring'/'r ing'/g' 2.txt 
sed: -e expression #1, char 8: unterminated `s' command
$ cat *.txt
this is a string
this is a string
$
$ _frf ring "r\ ing" "*.txt"
Replacing ring with r\ ing in all *.txt files...
sh -c sed -i 's/'ring'/'r\ ing'/g' 1.txt 
sh -c sed -i 's/'ring'/'r\ ing'/g' 2.txt 
$ cat *.txt
this is a str ing
this is a str ing

Open in new window

Curiosity: Notice in my previous post at line 23, there is "*.txt", and I got both files correctly changed. Below, I leave out the quotes, and the results differ from Duncan's experiments. I am using Centos7.
$ cat *.txt
this is a string
this is a string
$ _frf ring "r\ ing" *.txt
Replacing ring with r\ ing in all 1.txt files...
sh -c sed -i 's/'ring'/'r\ ing'/g' 1.txt 
$ cat *.txt
this is a str ing
this is a str ing
$ cat *.txt
this is a str ing
this is a string

Open in new window

@phoffric: you should be using frf, not _frf. Perhaps partly my fault because I didn't keep posting
alias frf='set -o noglob;_frf'

Open in new window

since it never changed from the beginning
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
I think I understand you. Outside the function, we turn off expansion so that the *.txt gets sent not expanded to the function, so that the $3 is *.txt. But within the function, we immediately turn expansion back on so that in the grep -li $1 $3, the *.txt gets expanded to both txt files.

Unfortunately, I get too much stuff being output when I use set -x. Weird, huh?
$ set -x
++ __vte_prompt_command
+++ sed 's/^ *[0-9]\+ *//'
+++ HISTTIMEFORMAT=
+++ history 1
++ local 'command=set -x'
++ command='set -x'
++ local 'pwd=~'
++ '[' /home/admin/Tst '!=' /home/admin ']'
++ pwd='~/Tst'
+++ __vte_osc7
++++ __vte_urlencode /home/admin/Tst
++++ LC_ALL=C
++++ str=/home/admin/Tst
++++ '[' -n /home/admin/Tst ']'
++++ safe=/home/admin/Tst
++++ printf %s /home/admin/Tst
++++ str=
++++ '[' -n '' ']'
++++ '[' -n '' ']'

Open in new window

And every time I hit the Enter or even ls -l, I get the above. (I have to scroll up to see the output of ls -l.) With the ls -l, I also get at the end:
+++ printf '\033]7;file://%s%s\007' localhost.localdomain /home/admin/Tst
++ printf '\033]777;notify;Command completed;%s\007\033]0;%s@%s:%s\007%s' ll admin localhost '~/Tst' ''

Open in new window

btw - I couldn't get strace to work with frf cmd line.
$ strace frf ring "r ing" *.txt
strace: Can't stat 'frf': No such file or directory
$
$ strace `frf ring "r ing" *.txt`
sh -c sed -i 's/'"ring"'/'"r ing"'/g' 1.txt 
sh -c sed -i 's/'"ring"'/'"r ing"'/g' 2.txt 
strace: Can't stat 'Replacing': No such file or directory

Open in new window

@arnold,
In general, all of us try to avoid having filenames with spaces in them. But, I tried to see if frf could handle it, but I wasn't able to take your remarks and make it work. Doesn't really matter though since dealing with these filenames isn't part of my considerations with this project. But thanks for the thought.

@Duncan,
Here is my slightly modified result. I added quotes around $1 so that I could have a space in the source string.
[admin@localhost Tst]$ type frf
frf is aliased to `frf_02'
[admin@localhost Tst]$ type frf_02
frf_02 is aliased to `set -o noglob;_frf_02'
[admin@localhost Tst]$ type _frf_02
_frf_02 is a function
_frf_02 () 
{ 
    \set +f;
    \echo "Replacing $1 with $2 in all $3 files...";
    \grep -li $1 $3 | \xargs -tI@ sh -c "sed -i 's/'\"$1\"'/'\"$2\"'/g' @"
}

Open in new window

Aside from not handling a space in a filename, this seems like a good solution that can handle spaces in either first or second argument. (Actually, when I tried to show you the following example, I had to change the - to a : (because frf hung up; so maybe not perfect, but good enough for now.)
[admin@localhost Tst]$ frf "is is" "is  : " *.txt
Replacing is is with is  :  in all *.txt files...
grep: is: No such file or directory
sh -c sed -i 's/'"is is"'/'"is  : "'/g' 1.txt 
sh -c sed -i 's/'"is is"'/'"is  : "'/g' 2.txt 
[admin@localhost Tst]$ cat *
this  :  a string
this  :  a string
$
[admin@localhost Tst]$ frf "s  :  a"  "s is a" *.txt
Replacing s  :  a with s is a in all *.txt files...
grep: :: No such file or directory
grep: a: No such file or directory
sh -c sed -i 's/'"s  :  a"'/'"s is a"'/g' 1.txt 
sh -c sed -i 's/'"s  :  a"'/'"s is a"'/g' 2.txt 
[admin@localhost Tst]$ cat *.txt
this is a string
this is a string

Open in new window

In the above example is a :
Originally, it was a -
When I tried to undo the change, I got hung. So the - in the undo must be a special char.
[admin@localhost Tst]$ cat *
this  -  a string
this  -  a string
[admin@localhost Tst]$ frf "s  -  a"   "s is a" *.txt
Replacing s  -  a with s is a in all *.txt files...
^C  (Just hung)

Open in new window

But this sort of worked:
[admin@localhost Tst]$ frf "s  \-  a"   "s is a" *.txt
Replacing s  \-  a with s is a in all *.txt files...
grep: \-: No such file or directory
grep: a: No such file or directory
sh -c sed -i 's/'"s  \-  a"'/'"s is a"'/g' 1.txt 
sh -c sed -i 's/'"s  \-  a"'/'"s is a"'/g' 2.txt 
$
[admin@localhost Tst]$ cat *
this is a string
this is a string

Open in new window

Despite the grep warnings/errors, the result came out ok.
The expansion you need for *.txt within the alias of frf is a double edged sword, it expands the "s -  a"
See if you have the same message if you use
frf  's is a' 's - a'
Hi Paul, you've been busy. I'll try to answer each of your posts in a separate post. This one tries to answer https:#a42987761
Unfortunately, I get too much stuff being output when I use set -x. Weird, huh?
Oh dear. I must be one of the last people in the world who shuns bash-completion. That's what you're seeing - scripts that "enhance" bash to complete arguments and so on. They severely degrade the usefulness of set -x used interactively.
With the ls -l, I also get at the end
These commands are generated by your prompt string, $PS1. The sequence ESC-close square bracket-7 starts a string that is written to the title bar of the terminal window. Over the years, I have evolved a prompt that gives me the time on the current line plus in the title bar <user>@<host>:<current working directory>. You are welcome to try it:
19:03:50$ echo "$PS1"
\[\e]0;${LOGNAME}@${HOSTNAME}:${PWD/#$HOME/"~"}\a\]\t\$ 

Open in new window

(There is a space at the end).
btw - I couldn't get strace to work with frf cmd line.
I amended the _frf function to put strace immediately before xargs:
alias frf='set -o noglob;_frf'

function _frf
{
    \set +f
    \echo "Replacing $1 with $2 in all $3 files..."
    \grep -li $1 $3 | \strace -f xargs -tI@ sh -c "sed -i 's/'$1'/'\"$2\"'/g' @"
}

Open in new window

In regard to https:#a42987817
The odd error messages are because you omitted to quote $1 when it is an argument to grep:
alias frf='set -o noglob;_frf'

function _frf
{
    \set +f
    \echo "Replacing $1 with $2 in all $3 files..."
    \grep -li "$1" $3 | \xargs -tI@ sh -c "sed -i 's/'\"$1\"'/'\"$2\"'/g' @"
}
frf "is is" "is  : " *.txt
Replacing is is with is  :  in all *.txt files...
sh -c sed -i 's/'"is is"'/'"is  : "'/g' 1.txt 
sh -c sed -i 's/'"is is"'/'"is  : "'/g' 2.txt 
cat *.txt
this  :  a string
this  :  a string
frf "is  : " "is is" *.txt
Replacing is  :  with is is in all *.txt files...
sh -c sed -i 's/'"is  : "'/'"is is"'/g' 1.txt 
sh -c sed -i 's/'"is  : "'/'"is is"'/g' 2.txt 
cat *.txt
this is a string
this is a string

Open in new window

By the way, why did you put semicolons at the end of the setecho lines? I really can't see what they achieve but am happy to be enlightened.
Commenting on https:#a42987820
As it happens, quoting $1 grep arg fixes it for minus as well:
21:35:06$ frf "is is" "is  - " *.txt
Replacing is is with is  -  in all *.txt files...
sh -c sed -i 's/'"is is"'/'"is  - "'/g' 1.txt 
sh -c sed -i 's/'"is is"'/'"is  - "'/g' 2.txt 
21:42:36$ cat *.txt
this  -  a string
this  -  a string
21:42:40$ frf "is  - " "is is" *.txt
Replacing is  -  with is is in all *.txt files...
sh -c sed -i 's/'"is  - "'/'"is is"'/g' 1.txt 
sh -c sed -i 's/'"is  - "'/'"is is"'/g' 2.txt 
21:42:53$ cat *.txt
this is a string
this is a string

Open in new window

So, no more to do here. I can't even break it with a leading minus in the search string (thought I might have to use grep -- to tell grep not to interpret the search string as a command option, which is what was happening to you earlier).
It's just as well spaces in filenames are out of scope. The usual way to deal with them is find ... -print0 | xargs -0 ... but that's not easily done here because of the ingenious use of $3 / noglob / glob
I think I am getting saturated. I will ask separate questions regarding my last few posts.
Thanks all.
Thanks again for all your help and creative juices while investigating a solution to this "hard" problem. (I had no idea this would be this complicated for me.)

Who invented this crazy bash language. I thought C++ was challenging, but this bash is crazy (at least from this OP question perspective).
I mentioned that I just installed Virtualbox in order to work on this problem. Here is $PS1
$ echo "$PS1"
[\u@\h \W]\$
I didn't follow how/why set -x is affected by $PS1, but that will be for another question.
I never had a -x problem on unix and linux before. Not sure what I did when I installed Centos 7.

@arnold,
>> The expansion you need for *.txt within the alias of frf is a double edged sword, it expands the "s -  a"
I don't understand what is the "double edged sword". I don't understand what *.txt expansion has to do with the string "s -  a".
>> See if you have the same message if you use
>> frf  's is a' 's - a'
Ok, but I don't see where we are going with this. Perhaps, you could tell me exactly what problem you are trying to expose.
[admin@localhost Tst]$ cat *.txt
this is a string
this is a string
[admin@localhost Tst]$ type frf
frf is aliased to `frf_02'
[admin@localhost Tst]$ type frf_02
frf_02 is aliased to `set -o noglob;_frf_02'
[admin@localhost Tst]$ type _frf_02
_frf_02 is a function
_frf_02 () 
{ 
    \set +f;
    \echo "Replacing $1 with $2 in all $3 files...";
    \grep -li $1 $3 | \xargs -tI@ sh -c "sed -i 's/'\"$1\"'/'\"$2\"'/g' @"
}
[admin@localhost Tst]$ frf  's is a' 's - a' 
Replacing s is a with s - a in all  files...
grep: is: No such file or directory
grep: a: No such file or directory

Open in new window

[admin@localhost Tst]$ frf  's is a' 's - a' *.txt
Replacing s is a with s - a in all *.txt files...
grep: is: No such file or directory
grep: a: No such file or directory
sh -c sed -i 's/'"s is a"'/'"s - a"'/g' 1.txt 
sh -c sed -i 's/'"s is a"'/'"s - a"'/g' 2.txt 
[admin@localhost Tst]$ cat *
this - a string
this - a string

Open in new window

[admin@localhost Tst]$ frf "s - a" "s is a" *.txt
Replacing s - a with s is a in all *.txt files...
      ****** HUNG UP HERE *************

Open in new window

Exampke variable assignment
Test=somedata

grep '$test' is different from grep "$test"
The second the variable will be expanded

Similarly, the -within double quotes is interpreted and grep sees is as a begining of an argument which is not properly referenced.

As you see, using single quotes while you received warnings/error messages the change occurred, ..
>> using single quotes while you received warnings/error messages the change occurred, ..
I am not sure what I am doing wrong in trying to follow your instructions. Whether I use single or double quotes in the previous example, I get the same results.