I want search with a wildcard and replace with same wildcard. For example search for specific fruits name and replace it with same names at different positions.
Input:
fruit_id "Apple"; salad_id "";
fruit_id "Mango"; salad_id "";
fruit_id "Kiwi"; salad_id "";
Expected output:
fruit_id "Apple"; salad_id "Apple";
fruit_id "Mango"; salad_id "Mango";
fruit_id "Kiwi"; salad_id "Kiwi";
I am using sed and for obvious reason it dosn't work:
sed 's/fruit_id "..*"; salad_id "";/fruit_id "..*"; salad_id "..*";/g'
You may capture the parts and use placeholders in the replacement that refer to the values captured:
sed 's/\(fruit_id "\([^"]*\)"; salad_id \)"";/\1"\2";/g' file > newfile
Details:
\(fruit_id "\([^"]*\)"; salad_id \) - Group 1 (\1):
fruit_id " - fruit_id " substring
\([^"]*\) - Group 2 (\2): any 0+ chars other than "
"; salad_id - a "; salad_id substring
""; - a ""; substring.
See the online demo:
s='fruit_id "Apple"; salad_id "";
fruit_id "Mango"; salad_id "";
fruit_id "Kiwi"; salad_id "";'
sed 's/\(fruit_id "\([^"]*\)"; salad_id \)"";/\1"\2";/g' <<< "$s"
Output:
fruit_id "Apple"; salad_id "Apple";
fruit_id "Mango"; salad_id "Mango";
fruit_id "Kiwi"; salad_id "Kiwi";
Try this :
sed 's/fruit_id "\([^"]*\)"; salad_id "";/fruit_id "\1"; salad_id "\1";/g'
The idea is to use a capture group using parenthesis, and then to re-use the captured text using \1
See this tool for a detailed explanation of your example :
https://regex101.com/r/N4sfGA/1
An awk solution
awk '{$4=$2}1' FS='"' OFS='"' file
fruit_id "Apple"; salad_id "Apple";
fruit_id "Mango"; salad_id "Mango";
fruit_id "Kiwi"; salad_id "Kiwi";
Split the data by " then copy data from second field to fourth field.
Related
I hope you're having a great day,
I want to remove two patterns, I want to remove the parts that contains the word images from a text that I have:
in the files test1 I have this:
APP:Server1:files APP:Server2:images APP:Server3:misc APP:Server4:xml APP:Server5:json APP:Server6:stats APP:Server7:graphs APP:Server8:images-v2
I need to remove APP:Server2:image and APP:Server8:images-v2 ... I want this output:
APP:Server1:files APP:Server3:misc APP:Server4:xml APP:Server5:json APP:Server6:stats APP:Server7:graphs
I'm trying this:
cat test1 | sed 's/ .*images.* / /g'
You need to make sure that your wildcards do not allow spaces:
cat data | sed 's/ [^ ]*image[^ ]* / /g'
This should work for you
sed 's/\w{1,}:Server[2|8]:\w{1,} //g'
\w matches word characters (letters, numbers, _)
{1,} matches one or more of the preceeding item (\w)
[2|8] matches either the number 2 or 8
cat test.file
APP:Server1:files APP:Server2:images APP:Server3:misc APP:Server4:xml APP:Server5:json APP:Server6:stats APP:Server7:graphs APP:Server8:images-v2
The below command removes the matching lines and leaves blanks in their place
tr ' ' '\n' < test.file |sed 's/\w\{1,\}:Server[2|8]:\w\{1,\}.*$//'
APP:Server1:files
APP:Server3:misc
APP:Server4:xml
APP:Server5:json
APP:Server6:stats
APP:Server7:graphs
To remove the blank lines, just add a second option to the sed command, and paste the contents back together
tr ' ' '\n' < test.file |sed 's/\w\{1,\}:Server[2|8]:\w\{1,\}.*$//;/^$/d'|paste -sd ' ' -
APP:Server1:files APP:Server3:misc APP:Server4:xml APP:Server5:json APP:Server6:stats APP:Server7:graphs
GNU aWk alternative:
awk 'BEGIN { RS="APP:" } $0=="" { next } { split($0,map,":");if (map[2] ~ /images/ ) { next } OFS=RS;printf " %s%s",OFS,$0 }'
Set the record separator to "APP:" and then process the text in between as separate records. If the record is blank, skip to the next record. Split the record into array map based on ":" as the delimiter, then check if there is image in the any of the text in the second index. If there is, skip to the next record, otherwise print along with the record separator.
I need to perform a global update on a KDB table to update two columns. For the FirstName column, I want to remove it's value for records which have empty string in the SecondName column, and for the FullName column I want to replace an encoded delimiter with a space for all rows in the table.
These need not be done in a single update statement if that helps.
update
FirstName:$[SecondName like ""; FirstName; ""],
FullName[FullName; " "; " "]
from table
}
I'm struggling with the syntax - the above is my best attempt but it doesn't work.
One way to achieve that in a sinlge update statement:
q) update FirstName:?[SecondName like ""; SecondName;FirstName], FullName:ssr[;" "; " "]#'FullName from table
For your update for the FirstName you need a ? rather than a $ as the Execution control operator. As it does the execution with a list rather than an atom.
For the FullName you will need to use ssr, which finds where string has " " and replaces it with " "
Which would give the following:
q)tab:([]FirstName:("aa";"cc");SecondName:("";"dd");FullName:("aa ";"cc dd"))
q)update FirstName:?[SecondName like ""; count[FirstName]#enlist""; FirstName],FullName:ssr[; " ";" "]each FullName from tab
FirstName SecondName FullName
-----------------------------
"" "" "aa "
"cc" "dd" "cc dd"
Hope this answers your question.
Regards,
Sander
I would recommend to do it in two steps
//create table with mock data
table: ([]FirstName: ("aaa";"ccc"); SecondName: ("bbb";""); FullName: ("aaa bbb";"ccc "));
//step1: set First to "" whenever SecondName is ""
table: update FirstName: (count i)#enlist"" from table where SecondName like "";
//step2: replace spaces in FullName
table: update FullName: ssr[;" ";" "] each FullName from table;
Got it I think:
table:update FirstName:(count i)#enlist "" from table where SecondName like "";
table:update FullName:{ ssr[x; " "; " "] } each FullName from table where FullName like "* *";
I have a file with this values:
[mik#mikypc ~]$ cat file.txt
id=cat8760004
id=cat1350003
id=cat9020002
And I want to insert id with the value above every line, so the result will be:
New_id=cat8760004
id=cat8760004
New_id=cat1350003
id=cat1350003
New_id=cat9020002
id=cat9020002
How could I do that?, I have tried with sed, but I cannot replace the variable:
[mik#mikypc ~]$ cat file.txt | sed '/cat\([0-9][0-9]*\)/ i\New_id &'
New_id &
id=cat8760004
New_id &
id=cat1350003
New_id &
id=cat9020002
I suggest with GNU sed:
sed 's/.*/New_&\n&/' file.txt
Output:
New_id=cat8760004
id=cat8760004
New_id=cat1350003
id=cat1350003
New_id=cat9020002
id=cat9020002
I have a csv file exported from spreadsheet which has, in the last column, sometimes a list of names. The file comes out like this:
ag,bd,cj,dy,"ss"
aa,bs,cs,fg,"name1
name2
name3
"
ff,ce,sd,de,
ag,bd,jj,ds,"ds"
fs,ee,sd,ee,"name4
name5
"
and so on.
I would like to remove the line feed in the last column between quotes so that the output is:
ag,bd,cj,dy,ss
aa,bs,cs,fg,"name1 name2 name3"
ff,ce,sd,de,
ag,bd,jj,ds,"ds"
fs,ee,sd,ee,"name4 name5"
Thanks
This awk may be one solution for you:
awk '/\"/ {s=!s} {printf "%s"(s?FS:RS),$0}'
ag,bd,cj,dy,ss
aa,bs,cs,fg,"name1 name2 name3 "
ff,ce,sd,de,df
New solution
awk -F\" 'NF==3; NF==2 {s++} s==1 {printf "%s ",$0} s==2 {print;s=0}' | awk '{sub(/ "/,"\"")}1' file
ag,bd,cj,dy,"ss"
aa,bs,cs,fg,"name1 name2 name3"
ag,bd,jj,ds,"ds"
fs,ee,sd,ee,"name4 name5"
I wanted to grep a string at the first occurrence ONLY from a file (file.dat) and replace it by reading from another file (output). I have a file called "output" as an example contains "AAA T 0001"
#!/bin/bash
procdir=`pwd`
cat output | while read lin1 lin2 lin3
do
srt2=$(echo $lin1 $lin2 $lin3 | awk '{print $1,$2,$3}')
grep -m 1 $lin1 $procdir/file.dat | xargs -r0 perl -pi -e 's/$lin1/$srt2/g'
done
Basically what I wanted is: When ever a string "AAA" is grep'ed from the file "file.dat" at the first instance, I want to replace the second and third column next to "AAA" by "T 0001" but still keep the first column "AAA" as it is. Th above script basically does not work. Basically "$lin1" and $srt2 variables are not understood inside 's/$lin1/$srt2/g'
Example:
in my file.dat I have a row
AAA D ---- CITY COUNTRY
What I want is :
AAA T 0001 CITY COUNTRY
Any comments are very appreciated.
If you have output file like this:
$ cat output
AAA T 0001
Your file.dat file contains information like:
$ cat file.dat
AAA D ---- CITY COUNTRY
BBB C ---- CITY COUNTRY
AAA D ---- CITY COUNTRY
You can try something like this with awk:
$ awk '
NR==FNR {
a[$1]=$0
next
}
$1 in a {
printf "%s ", a[$1]
delete a[$1]
for (i=4;i<=NF;i++) {
printf "%s ", $i
}
print ""
next
}1' output file.dat
AAA T 0001 CITY COUNTRY
BBB C ---- CITY COUNTRY
AAA D ---- CITY COUNTRY
Say you place the string for which to search in $s and the string with which to replace in $r, wouldn't the following do?
perl -i -pe'
BEGIN { ($s,$r)=splice(#ARGV,0,2) }
$done ||= s/\Q$s/$r/;
' "$s" "$r" file.dat
(Replaces the first instance if present)
This will only change the first match in the file:
#!/bin/bash
procdir=`pwd`
while read line; do
set $line
sed '0,/'"$1"'/s/\([^ ]* \)\([^ ]* [^ ]*\)/\1'"$2 $3"'/' $procdir/file.dat
done < output
To change all matching lines:
sed '/'"$1"'/s/\([^ ]* \)\([^ ]* [^ ]*\)/\1'"$2 $3"'/' $procdir/file.dat