Replace strings with evaluated string based on matched group (elegant way, not using for .. in)
awk oneliner: (the datetime format could be different from your output)
awk '/^[0-9]{1,10} [0-9]{1,4}/{l=$1+$2; "date --date=@"$1|getline d1; "date --date=@"l|getline d2;print d1" - "d2;next;}1' file
test:
kent$ echo "1357222500 3600 ...
Maybe intermediate strings...
1357226100 3600 ...
Maybe intermediate strings...
..."|awk '/^[0-9]{1,10} [0-9]{1,4}/{l=$1+$2; "date --date=@"$1|getline d1; "date --date=@"l|getline d2;print d1" - "d2;next;}1'
Thu Jan 3 15:15:00 CET 2013 - Thu Jan 3 16:15:00 CET 2013
Maybe intermediate strings...
Thu Jan 3 15:15:00 CET 2013 - Thu Jan 3 17:15:00 CET 2013
Maybe intermediate strings...
...
Gnu sed
if you have gnu sed, the idea from your "not working" sed line could work in real world by applying gnu sed's s/foo/shell cmds/ge
see below:
sed -r 's#^([0-9]{1,10}) ([0-9]{1,4})(.*$)#echo $(date --date=@\1 )" - "$(date --date=@$((\1+\2)))#ge' file
test
kent$ echo "1357222500 3600 ...
Maybe intermediate strings...
1357226100 3600 ...
Maybe intermediate strings...
..."|sed -r 's#^([0-9]{1,10}) ([0-9]{1,4})(.*$)#echo $(date --date=@\1 )" - "$(date --date=@$((\1+\2)))#ge'
Thu Jan 3 15:15:00 CET 2013 - Thu Jan 3 16:15:00 CET 2013
Maybe intermediate strings...
Thu Jan 3 16:15:00 CET 2013 - Thu Jan 3 17:15:00 CET 2013
Maybe intermediate strings...
...
if I would work on this, personally I would go with awk. because it is straightforward and easy to write.
at the end I paste my sed/awk version info :
kent$ sed --version|head -1
sed (GNU sed) 4.2.2
kent$ awk -V|head -1
GNU Awk 4.0.1
Java string replace regex pattern with evaluated key
You should make use of the Matcher#appendReplacement
and Matcher#appendTail
APIs here:
Map<String, String> keyValueMap = new HashMap<>();
keyValueMap.put("places", "to America");
keyValueMap.put("things", "events");
String input = "I want to go to {places} where {things} are happening.";
Pattern pattern = Pattern.compile("\\{(.*?)\\}");
Matcher matcher = pattern.matcher(input);
StringBuffer buffer = new StringBuffer();
while(matcher.find()) {
matcher.appendReplacement(buffer, keyValueMap.get(matcher.group(1)));
}
matcher.appendTail(buffer);
System.out.println(buffer.toString());
This prints:
I want to go to to America where events are happening.
Replace named group in regex with value
No, it's not possible to use a regular expression without providing input. It has to have something to work with, the pattern can not add any data to the result, everything has to come from the input or the replacement.
Intead of using String.Format, you can use a look behind and a look ahead to specify the part between "abc_" and "_def", and replace it:
string result = Regex.Replace(input, @"(?<=abc_)\d+(?=_def)", "999");
Replace multiple strings with multiple other strings
As an answer to:
looking for an up-to-date answer
If you are using "words" as in your current example, you might extend the answer of Ben McCormick using a non capture group and add word boundaries \b
at the left and at the right to prevent partial matches.
\b(?:cathy|cat|catch)\b
\b
A word boundary to prevent a partial match(?:
Non capture groupcathy|cat|catch
match one of the alternatives
)
Close non capture group\b
A word boundary to prevent a partial match
Example for the original question:
let str = "I have a cat, a dog, and a goat.";
const mapObj = {
cat: "dog",
dog: "goat",
goat: "cat"
};
str = str.replace(/\b(?:cat|dog|goat)\b/gi, matched => mapObj[matched]);
console.log(str);
Not able to build an array & print it out in AWK
index
is built-in GNU AWK
function, thus you have syntax error when you try to use it as array key. Change index
to inx
to avoid syntax error and apply some changes to last action to get desired output
Let file.txt
content be
1|Sam|Smith|Seatle
2|Barry|Jones|Seatle
3|Garry|Brown|Houston
4|George|Bla|LA
5|Celine|Wood|Atlanta
6|Jody|Ford|Chicago
then
awk 'BEGIN { FS="|" } { employee[$1]=$0; next } END{ for (inx=1; inx<=NR; inx++){print inx ":" employee[inx]} }' file.txt
output
1:1|Sam|Smith|Seatle
2:2|Barry|Jones|Seatle
3:3|Garry|Brown|Houston
4:4|George|Bla|LA
5:5|Celine|Wood|Atlanta
6:6|Jody|Ford|Chicago
7:
Explanation: changed index
to inx
, change for
's check to less equal number of rows (NR
), register last action as END
(execute after processing all files). Note that for
for Arrays might be better fit for that rather than for
you have used depending on your requirements.
(tested in gawk 4.2.1)
Regex C# replace matched fields with multiple results
I would use some lambda functions:
// This one gets the index from the list of matches
private static string LookupReplace(string text, List<string> newList)
{
var result = "~" + newList.IndexOf(text).ToString() + "~";
return result;
}
// This one just increments a global counter
private static string NumberedReplace()
{
i++;
return "~" + i.ToString() + "~";
}
public static int i = -1;
public static void Main()
{
string text = "iif(instr(|Wellington, New Zealand|,|,|)>0,|Wellington, New Zealand|,|Wellington, New Zealand| & |, | & |New Zealand|) & | to | & iif(instr(|Jeddah, Saudi Arabia|,|,|)>0,|Jeddah, Saudi Arabia|,|Jeddah, Saudi Arabia| & |, | & |Saudi Arabia|) & iif(|Jeddah, Saudi Arabia|=||,||,| via | & |Jeddah, Saudi Arabia|)";
var re = new Regex(@"\|.*?\|");
var newList = re.Matches(text)
.OfType<Match>()
.Select(m => m.Value)
.ToList();
// First replace with index
string result = re.Replace(text, x => LookupReplace(x.Value, newList));
Console.WriteLine(result);
// Second replace with counter
result = re.Replace(text, x => NumberedReplace());
Console.WriteLine(result);
}
ideone demo
Output of each replace:
iif(instr(~0~,~1~)>0,~0~,~0~ & ~4~ & ~5~) & ~6~ & iif(instr(~7~,~1~)>0,~7~,~7~ & ~4~ & ~12~) & iif(~7~=~14~,~14~,~16~ & ~7~)
iif(instr(~0~,~1~)>0,~2~,~3~ & ~4~ & ~5~) & ~6~ & iif(instr(~7~,~8~)>0,~9~,~10~ & ~11~ & ~12~) & iif(~13~=~14~,~15~,~16~ & ~17~)
R - How to replace a string from multiple matches (in a data frame)
Edit
Based on the input from Sri's comment I would suggest using:
library(gsubfn)
# words to be replaced
a <-c("Whats your","Whats your name", "name", "fro")
# their replacements
b <- c("What is yours","what is your name","names","froth")
# named list as an input for gsubfn
replacements <- setNames(as.list(b), a)
# the test string
input_string = "fro Whats your name and Where're name you from to and fro I Whats your"
# match entire words
gsubfn(paste(paste0("\\w*", names(replacements), "\\w*"), collapse = "|"), replacements, input_string)
Original
I would not say this is easier to read than your simple loop, but it might take better care of the overlapping replacements:
# define the sample dataset
input_string = "Whats your name and Where're you from"
matching <- data.frame(from_word=c("Whats your name", "name", "fro", "Where're", "Whats"),
to_word=c("what is your name","names","froth", "where are", "Whatsup"))
# load used library
library(gsubfn)
# make sure data is of class character
matching$from_word <- as.character(matching$from_word)
matching$to_word <- as.character(matching$to_word)
# extract the words in the sentence
test <- unlist(str_split(input_string, " "))
# find where individual words from sentence match with the list of replaceble words
test2 <- sapply(paste0("\\b", test, "\\b"), grepl, matching$from_word)
# change rownames to see what is the format of output from the above sapply
rownames(test2) <- matching$from_word
# reorder the data so that largest replacement blocks are at the top
test3 <- test2[order(rowSums(test2), decreasing = TRUE),]
# where the word is already being replaced by larger chunk, do not replace again
test3[apply(test3, 2, cumsum) > 1] <- FALSE
# define the actual pairs of replacement
replacements <- setNames(as.list(as.character(matching[,2])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1]),
as.character(matching[,1])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1])
# perform the replacement
gsubfn(paste(as.character(matching[,1])[order(rowSums(test2), decreasing = TRUE)][rowSums(test3) >= 1], collapse = "|"),
replacements,input_string)
Replace matches with regex
Something like this might do:
const evaluate = function(str) {
if (str && str.startsWith("t")) {return str.toUpperCase();}
throw "Gotta hava a 'T'";
};
"ab$test$cd $something$ that is $tricky$.".replace(/\$([^$]*)\$/g;, function(str, match) {
try {
return evaluate(match);
} catch(e) {
return str;
}
}); //=> "abTESTcd $something$ that is TRICKY."
But I agree with the comment that you might be better returning a different signal (undefined
? null
?) from evaluate
rather than throwing for this case. And then the function body could simply be something like:
return evaluate(match) || str;
The point is the capturing group in the regex: /\$([^$]*)\$/g;
, which becomes a parameter to the replacement function.
Related Topics
Aborting a Blocking Read on Linux
How to Get Pyinstaller to Working on Ubuntu
How to Create a File in Assembly with a Dynamically Specified File Path
Shared Libraries (Dlopen) and Thread-Safety of Library Static Pointers
Mqtt Socket Error on Client <Unknown>
When Did Hup Stop Getting Sent and What How to Do About It
Setting The Umask of The Jenkins Process
Docker Can't Write to Directory Mounted Using -V Unless It Has 777 Permissions
Can Not Route Packets from One Interface to Another
Binding on a Port with Netpipes/Netcat
Set Cron Job for 1St Working Day of Every Month in Shell Scripting
Where The Structure "Struct Page" Is Stored on The Linux Kernel
Running Meteor Application on a Single Core
How to Send Email from The Command Line
Snort Message - Warning: No Preprocessors Configured for Policy 0