I have the following .sed script:
# replace female-male with F-M
s/female/F/
s/male/M/
# capitalize the name when the sport is volleyball or taekwondo
s/^([^,]*,)([^,]+)((,[^,]*){5},(volleyball|taekwondo),)/\1\U\2\L\3/
And the following csv file (first 10 lines)
id,name,nationality,sex,date_of_birth,height,weight,sport,gold,silver,bronze,info
736041664,A Jesus Garcia,ESP,male,1969-10-17,1.72,64,athletics,0,0,0,
532037425,A Lam Shin,KOR,female,1986-09-23,1.68,56,handball,0,0,0,
435962603,Aaron Brown,CAN,male,1992-05-27,1.98,79,athletics,0,0,1,
521041435,Aaron Cook,MDA,male,1991-01-02,1.83,80,taekwondo,0,0,0,
33922579,Aaron Gate,NZL,male,1990-11-26,1.81,,cycling,0,0,0,
173071782,Aaron Royle,AUS,male,1990-01-26,1.80,67,triathlon,0,0,0,
266237702,Aaron Russell,USA,male,1993-06-04,,98,volleyball,0,0,1,
382571888,Aaron Younger,AUS,male,1991-09-25,1.93,100,football,0,0,0,
87689776,Aauri Lorena Bokesa,ESP,female,1988-12-14,1.80,62,athletics,0,0,0,
The output must be done by the following command
sed -f script.sed ./file.csv
The problem I have is that despite making sure the regex is matching all the pertinent lines, I can only get it to replace the female-male values with F-M, the rest of the file is still the exact same. The names are not being capitalized.
If I run each regex directly (i.e 'sed -E 's/^([^,],)([^,]+)((,[^,]){5},(volleyball|taekwondo),)/\1\U\2\L\3/' file.csv') it works. But I need to do it via script, and with -f.
What am I missing? Thank you.
You still need to indicate that you're using extended regular expresssions:
sed -Ef script.sed file.csv
Otherwise, sed uses basic regular expressions, where escaping rules are different, specifically for () for capture groups, and {} for counts.
Have you tried using sed -Ef <script> <csv file>? You need -E to use extended regex expressions.
This question already has answers here:
awk unable to ignore "++"
(2 answers)
Closed 1 year ago.
I am trying to create some useful aliases for myself and am trying to find a way see the current Kubernetes context namespace.
k config get-contexts
CURRENT NAME CLUSTER AUTHINFO NAMESPACE
* kubernetes-test#kubernetes2 kubernetes2 kubernetes-test test
kubernetes-admin#kubernetes kubernetes kubernetes-admin default
I only want the output to be 'test', so I tried:
k config get-contexts | awk '/*/{print $5}'
The error it gets:
awk: line 1: regular expression compile failed (missing operand)
You're getting that error message because * is a regexp repetition metachar and as such using it as the first char in a regexp is undefined behavior since there's nothing preceding it to repeat. You're also using a partial line regexp match when what you apparently want is a full word string match (see How do I find the text that matches a pattern? for the difference):
k config get-contexts | awk '$1=="*"{ print $5 }'
First of all, * in regex is a quantifier that means "zero or more occurrences". Since it is a regex metacharacter, it should be escaped, \*:
k config get-contexts | awk '/\*/{print $5}'
However, since you are looking for a fixed string rather than a pattern you can use index:
k config get-contexts | awk 'index($0, "*") {print $5}'
If * is found anywhere inside a "record" (the line) the fifth field will get printed.
I have the following sample strings:
Program exiting with code: 0.
Program exiting with code: 1.
Program exiting with code: 10.
I want grep to return values after the matching pattern "Program exiting with code:". However I do not need the period at the end. I have tried:
grep "Program exiting with exit code:" dataload.log | sed 's/^.*.: //'
The above command returns:
0.
1.
10.
I want to ignore the period at end. I picked up the above command from somewhere.
Can someone describe what each keyword represents and provide me with a regex that will only provide me with the value without period?
sed, awk, perl or any other way is fine with me.
Just use grep with a look-behind and catch only digits:
$ grep -Po '(?<=Program exiting with code: )\d*' file
0
1
10
sed 's/^.*.: //'
First of all this is a substition regular expression, as denoted by the s at the start. The part in the first / / is what to match and the second / / is what to replace it with.
The characters in the first (match) part of the expression are all special regular expression characters.
A full list of what they mean can be found here: http://www.rexegg.com/regex-quickstart.html
The match means:
^ - At the start of the line
. - Match any character
* - Any number of times
. - Match any character
: - Match a colon
- Match a space
And then that is all replaced with nothing. That is why the period at the end is kept because it removes everything up to Program exiting with code:, which leaves 1.
It's worth playing around with an interactive tool to test different regular expressions on your string, e.g. http://www.regexr.com/
You can probably just substitute/remove everything that is not a number in your case: 's/[^0-9]//g'.
This is another way:
grep -oE 'Program exiting with code:\s*[0-9]+' dataload.log |grep -oE '[0-9]+$'
Output of the first grep command is:
Program exiting with code: 0
Program exiting with code: 1
Program exiting with code: 10
Then you just grep the last digits.
Your solution is just fine if you extend it with a cut command:
grep "Program exiting with code:" dataload.log | sed 's/^.*.: //' | cut -d"." -f1
I am trying to remove a certain element from a list in korn shell. It's working on my linux machine but the exact same code gives me an error on a solaris11 machine. I need a code that will work for both. It's probably because of different ksh versions but I would like to find a solution that works for both.
The code is:
#!/bin/ksh
MY_LIST="HELLO HOW ARE YOU"
toDel="HOW"
MY_LIST=( "${MY_LIST[#]/$toDel}" )
echo "MY LIST AFTER REMOVING HOW IS $MY_LIST"
On Solaris I get the following error:
syntax error at line 4 : '(' unexpected
Any suggestions?
Melodie wrote: Finally, I used 'Walter A' solution
Nice I could help.
Enabling you to vote for me and close the question, I post my comment as an answer.
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`
You'll probably need to spend some time with the ksh88 man page.
Without futher explanation:
set -A my_list HELLO HOW ARE YOU # note, separate words
toDel=HOW
set -- # using positional parameters as "temp array"
for word in "${my_list[#]}"; do
[[ $word != $toDel ]] && set -- "$#" "$word"
done
set -A my_list "$#"
printf "%s\n" "${my_list[#]}"
HELLO
ARE
YOU
Finally, I used 'Walter A' solution:
MY_LIST=`echo $MY_LIST | sed "s/$toDel//"`
I couldn't find an answer for this exact problem, so I'll ask it.
I'm working in Cygwin and want to reference previous commands using !n notation, e.g., if command 5 was which ls, then !5 runs the same command.
The problem is when trying to do substitution, so running:
!5:s/which \([a-z]\)/\1/
should just run ls, or whatever the argument was for which for command number 5.
I've tried several ways of doing this kind of substitution and get the same error:
bash: :s/which \([a-z]*\)/\1/: substitution failed
As far as I can tell the s/old/new/ history substitution syntax only does simple string substitution; it does not support full regexes. Here's what man bash has to say:
s/old/new/
Substitute new for the first occurrence of old in the event line. Any delimiter can be used in place of /. The final delimiter is optional if it is the last character of the event line. The delimiter may be quoted in old and new with a single backslash. If & appears in new, it is replaced by old. A single backslash will quote the &. If old is null, it is set to the last old substituted, or, if no previous history substitutions took place, the last string in a !?string[?] search.
Never fear, though. There are in fact easier ways to accomplish what you are trying to do:
!$ evaluates to the last argument of the previous command:
# ls /etc/passwd
/etc/passwd
# vim !$
vim /etc/passwd
!5:$ evaluates to the last argument of command #5:
# history
...
5: which ls
...
# !5:$
ls
You can also use Alt+. to perform an immediate substitution equivalent to !$. Alt+. is one of the best bash tricks I know.
This worked for me using Bash in Cygwin (note that my which ls command was number 501 in my history list; not 5 like yours):
$(!501 | sed 's/which \([a-z]\)/\1/')
You could also do it this way (which is shorter/cleaner):
$(!501 | sed 's/which //')