How to avoid redundant substitutes in sed?

Clash Royale CLAN TAG#URR8PPP
up vote
0
down vote
favorite
1st file contains:
#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
FilNam=Project2128/Input/waveheightNew.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi
2nd file contains:
#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
FilNam=Project2128/Input/waveheightNewBin.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi
Now I need to process the files by changing .txt to Bin.txt?
Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.
Would it be smarter to skip the unwanted matches?
sed
add a comment |Â
up vote
0
down vote
favorite
1st file contains:
#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
FilNam=Project2128/Input/waveheightNew.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi
2nd file contains:
#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
FilNam=Project2128/Input/waveheightNewBin.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi
Now I need to process the files by changing .txt to Bin.txt?
Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.
Would it be smarter to skip the unwanted matches?
sed
add a comment |Â
up vote
0
down vote
favorite
up vote
0
down vote
favorite
1st file contains:
#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
FilNam=Project2128/Input/waveheightNew.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi
2nd file contains:
#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
FilNam=Project2128/Input/waveheightNewBin.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi
Now I need to process the files by changing .txt to Bin.txt?
Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.
Would it be smarter to skip the unwanted matches?
sed
1st file contains:
#. This is the file name to process: waveheight.txt
#. This is the latest data to process if exists: waveheightNew.txt
FilNam=Project2128/Input/waveheightNew.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheight.txt; fi
2nd file contains:
#. This is the file name to process: waveheightBin.txt
#. This is the latest data to process if exists: waveheightNewBin.txt
FilNam=Project2128/Input/waveheightNewBin.txt
if [[ ! -f $FilNam ]]; then FilNam=Project2128/Input/waveheightBin.txt; fi
Now I need to process the files by changing .txt to Bin.txt?
Using sed "s/.txt/Bin.txt/" will lead to BinBin.txt for the 2nd file.
By sed "s/Bin.txt/.txt/" and then sed "s/.txt/Bin.txt/" seems awkward.
Would it be smarter to skip the unwanted matches?
sed
sed
edited Sep 19 at 7:03
Sparhawk
8,53863489
8,53863489
asked Sep 19 at 6:56
MathArt
32
32
add a comment |Â
add a comment |Â
4 Answers
4
active
oldest
votes
up vote
3
down vote
accepted
You could include the Bin in the text to replace if there which would then result in it being replaced with itself:
sed 's/(Bin)0,1.txt/Bin.txt/g'
Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):
sed -E 's/(Bin)?.txt/Bin.txt/g'
Beware . is a regexp operator that matches any single character. You need . to match a literal dot.
add a comment |Â
up vote
2
down vote
You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.
perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Hence, to test:
$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Bin.txt fooBin.txt
Unfortunately, sed does not offer this construct.
Depends on thesedimplementation,ssedsupports it with-Rand ast-opensedwith-E/-ror-A/-X.
â Stéphane Chazelas
Sep 19 at 7:23
add a comment |Â
up vote
1
down vote
You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.
sed '/Bin.txt/!s/.txt/Bin.txt/'
This assumes that there will only be need for one substitution per line.
You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:
sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'
add a comment |Â
up vote
0
down vote
You could do this with GNU-sed as shown:
echo "$Filnam" |
sed -e '
s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
# existed in the name, so we needn"t do anything n take away the marker n quit
s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
'
### Below is the POSIX sed code for accomplishing the same:
sed -e '
s/.txt/
&/;/n/!b
s/Binn/Bin/;/n/!b
s/n/Bin/
'
add a comment |Â
4 Answers
4
active
oldest
votes
4 Answers
4
active
oldest
votes
active
oldest
votes
active
oldest
votes
up vote
3
down vote
accepted
You could include the Bin in the text to replace if there which would then result in it being replaced with itself:
sed 's/(Bin)0,1.txt/Bin.txt/g'
Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):
sed -E 's/(Bin)?.txt/Bin.txt/g'
Beware . is a regexp operator that matches any single character. You need . to match a literal dot.
add a comment |Â
up vote
3
down vote
accepted
You could include the Bin in the text to replace if there which would then result in it being replaced with itself:
sed 's/(Bin)0,1.txt/Bin.txt/g'
Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):
sed -E 's/(Bin)?.txt/Bin.txt/g'
Beware . is a regexp operator that matches any single character. You need . to match a literal dot.
add a comment |Â
up vote
3
down vote
accepted
up vote
3
down vote
accepted
You could include the Bin in the text to replace if there which would then result in it being replaced with itself:
sed 's/(Bin)0,1.txt/Bin.txt/g'
Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):
sed -E 's/(Bin)?.txt/Bin.txt/g'
Beware . is a regexp operator that matches any single character. You need . to match a literal dot.
You could include the Bin in the text to replace if there which would then result in it being replaced with itself:
sed 's/(Bin)0,1.txt/Bin.txt/g'
Or if your sed supports EREs with -E (or -r for some older versions of GNU or busybox sed):
sed -E 's/(Bin)?.txt/Bin.txt/g'
Beware . is a regexp operator that matches any single character. You need . to match a literal dot.
edited Sep 19 at 10:11
answered Sep 19 at 7:17
Stéphane Chazelas
287k53528867
287k53528867
add a comment |Â
add a comment |Â
up vote
2
down vote
You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.
perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Hence, to test:
$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Bin.txt fooBin.txt
Unfortunately, sed does not offer this construct.
Depends on thesedimplementation,ssedsupports it with-Rand ast-opensedwith-E/-ror-A/-X.
â Stéphane Chazelas
Sep 19 at 7:23
add a comment |Â
up vote
2
down vote
You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.
perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Hence, to test:
$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Bin.txt fooBin.txt
Unfortunately, sed does not offer this construct.
Depends on thesedimplementation,ssedsupports it with-Rand ast-opensedwith-E/-ror-A/-X.
â Stéphane Chazelas
Sep 19 at 7:23
add a comment |Â
up vote
2
down vote
up vote
2
down vote
You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.
perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Hence, to test:
$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Bin.txt fooBin.txt
Unfortunately, sed does not offer this construct.
You can use a perl negative lookbehind to match .txt, but only it it's not Bin.txt.
perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Hence, to test:
$ echo 'Bin.txt foo.txt' | perl -pe 's/(?<!Bin).txt/Bin.txt/g'
Bin.txt fooBin.txt
Unfortunately, sed does not offer this construct.
edited Sep 19 at 8:17
answered Sep 19 at 7:14
Sparhawk
8,53863489
8,53863489
Depends on thesedimplementation,ssedsupports it with-Rand ast-opensedwith-E/-ror-A/-X.
â Stéphane Chazelas
Sep 19 at 7:23
add a comment |Â
Depends on thesedimplementation,ssedsupports it with-Rand ast-opensedwith-E/-ror-A/-X.
â Stéphane Chazelas
Sep 19 at 7:23
Depends on the
sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.â Stéphane Chazelas
Sep 19 at 7:23
Depends on the
sed implementation, ssed supports it with -R and ast-open sed with -E/-r or -A/-X.â Stéphane Chazelas
Sep 19 at 7:23
add a comment |Â
up vote
1
down vote
You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.
sed '/Bin.txt/!s/.txt/Bin.txt/'
This assumes that there will only be need for one substitution per line.
You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:
sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'
add a comment |Â
up vote
1
down vote
You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.
sed '/Bin.txt/!s/.txt/Bin.txt/'
This assumes that there will only be need for one substitution per line.
You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:
sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'
add a comment |Â
up vote
1
down vote
up vote
1
down vote
You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.
sed '/Bin.txt/!s/.txt/Bin.txt/'
This assumes that there will only be need for one substitution per line.
You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:
sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'
You may do a conditional substitution with sed, for example, you may test whether the line already contains Bin.txt and only perform the substitution if it doesn't.
sed '/Bin.txt/!s/.txt/Bin.txt/'
This assumes that there will only be need for one substitution per line.
You may also do the substitution unconditionally, and then correct it if it went wrong, as you hinted at in the question, but in the same call to sed:
sed -e 's/.txt/Bin.txt/' -e 's/BinBin/Bin/'
edited Sep 19 at 10:26
answered Sep 19 at 7:10
Kusalananda
108k14209332
108k14209332
add a comment |Â
add a comment |Â
up vote
0
down vote
You could do this with GNU-sed as shown:
echo "$Filnam" |
sed -e '
s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
# existed in the name, so we needn"t do anything n take away the marker n quit
s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
'
### Below is the POSIX sed code for accomplishing the same:
sed -e '
s/.txt/
&/;/n/!b
s/Binn/Bin/;/n/!b
s/n/Bin/
'
add a comment |Â
up vote
0
down vote
You could do this with GNU-sed as shown:
echo "$Filnam" |
sed -e '
s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
# existed in the name, so we needn"t do anything n take away the marker n quit
s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
'
### Below is the POSIX sed code for accomplishing the same:
sed -e '
s/.txt/
&/;/n/!b
s/Binn/Bin/;/n/!b
s/n/Bin/
'
add a comment |Â
up vote
0
down vote
up vote
0
down vote
You could do this with GNU-sed as shown:
echo "$Filnam" |
sed -e '
s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
# existed in the name, so we needn"t do anything n take away the marker n quit
s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
'
### Below is the POSIX sed code for accomplishing the same:
sed -e '
s/.txt/
&/;/n/!b
s/Binn/Bin/;/n/!b
s/n/Bin/
'
You could do this with GNU-sed as shown:
echo "$Filnam" |
sed -e '
s/.txt/n&/;T # try to place a newline marker to the left of .txt, quit if unsuccessful
s/Binn/Bin/;t # If the marker turned out to be just to the right of Bin => Bin.txt already
# existed in the name, so we needn"t do anything n take away the marker n quit
s/n/Bin/ # Bin could not be found adjacent to .txt so put it n take away the marker as well
'
### Below is the POSIX sed code for accomplishing the same:
sed -e '
s/.txt/
&/;/n/!b
s/Binn/Bin/;/n/!b
s/n/Bin/
'
answered Sep 20 at 4:56
Rakesh Sharma
64513
64513
add a comment |Â
add a comment |Â
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
StackExchange.ready(
function ()
StackExchange.openid.initPostLogin('.new-post-login', 'https%3a%2f%2funix.stackexchange.com%2fquestions%2f469939%2fhow-to-avoid-redundant-substitutes-in-sed%23new-answer', 'question_page');
);
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Post as a guest
Sign up or log in
StackExchange.ready(function ()
StackExchange.helpers.onClickDraftSave('#login-link');
);
Sign up using Google
Sign up using Facebook
Sign up using Email and Password
Sign up using Google
Sign up using Facebook
Sign up using Email and Password