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.
I would request some help with a basic shell script that should do the following job.
File a particular word from a given file (file path is always constant)
Backup the file
Delete the specific word or replace the word with ;
Save the file changes
Example
File Name - abc.cfg
Contains the following lines
network;private;Temp;Windows;System32
I've used the following SED command for the operation
sed -i -e "/Temp;/d" abc.cfg
The output is not as expected. The complete line is removed instead of just the word Temp;
Any help would be appreciated. Thank you
sed matches against lines, and /d is the delete directive, which is why you get a deleted line. Instead, use substitution to replace the offending word with nothing:
sed 's/Temp;//g' abc.cfg
The /g modifier means "globlal", in case the offending word appears more than once. I would hold off on the -i (inline) flag until you are sure of your command, in general, or use -i .backup.
Thank you. I used your suggestion but couldn't get through. I appreciate the input though.
I was able to achieve this using the following SED syntax
sed -e "s/Temp//g" -i.backup abc.cfg
I wanted to take the backup before the change & hence -i was helpful.
I'm trying to take an environment variable in travis-ci and replace the contents of a file at runtime using sed.
The file in question contains:
service_name: travis-ci
repo_token: COVERALLS_TOKEN
On an ubuntu system, using sed -i 's/COVERALLS_TOKEN/ASDF/g' .coveralls.yml in the command line works, but carrying that over to the travis-ci configuration something like sed -i 's/COVERALLS_TOKEN/$COVERALLS_TOKEN/g' .coveralls.yml doesn't pull the environment variable.
What really throws me off is that I have a project today where the below .travis.yml entry works, but adapting it to this circumstances it doesn't.
Original implementation, still works today
sed -ri 's/^MY_ENV_VAR=/MY_ENV_VAR='$MY_ENV_VAR'/' .env
Adaptation (doesn't work)
sed -ri 's/^COVERALLS_TOKEN/$COVERALLS_TOKEN/' .coveralls.yml
You have two problems with your command. First, the ^ means it will only match COVERALLS_TOKEN where it occurs at the very beginning of a line. Since it's not at the beginning of a line in your YAML file, there is no match and the sed command does nothing.
Second, there is no variable substitution inside single quotation marks.
So remove the ^and use double quotes instead of single ones:
sed -ri "s/COVERALLS_TOKEN/$COVERALLS_TOKEN/" .coveralls.yml
Some notes:
The variable $COVERALLS_TOKEN must be set in the shell at the time that you run the sed command.
The substitution will fail with a syntax error if the value of $COVERALLS_TOKEN contains the delimiter you use on the substitution command. The command above uses /, but you can change that if needed - just pick something that doesn't occur in the token string.
The token value will not be quoted in any way in the YAML file. Normally that's ok, but if there are any weird characters in the value, you will need to put quotes around it in the YAML by adding them to the replacement side of the substitution command as well:
sed -ri "s/COVERALLS_TOKEN/'$COVERALLS_TOKEN'/" .coveralls.yml
The single quotes suppress variable expansion.
This is works for me.
sed -ri 's,IMAGE_REPOSITORY,'"$IMAGE_REPO"',g' chart/values.yaml
I'm using zsh, and am trying to write a function to operate on a URL and a pathname:
function my-function
{
somecommand --url $1 $(readlink -f $2)
}
(to complicate things somewhat, the function actually uses sh syntax, as it is sourced from my ~/.zshrc using a trick like this). The readlink is there to expand symlinks and ensure directories such as . are evaluated correctly (the directory name is stored for later use by somecommand).
When I type a command from the command-line like this:
my-function http://example.org/example /tmp/myexampledirectory
... it works fine, even if I autocomplete the directory name. However, if the directory name contains spaces, zsh completes it like this:
my-function http://example.org/example /tmp/My\ Example\ Directory
For most "normal" commands (cp, mv, etc.) that never seems to cause a problem. However, in my case, somecommand sees $2 as only being /tmp/My - presumably the rest is seen as another argument.
How can I avoid this situation? I would prefer not to alter the standard zsh autocompletion, but rather find a way for my function to handle this.
The zsh completion system works very well here, and the solution is very simple, just put double-quotes around the readlink argument in the script:
somecommand --url $1 $(readlink -f "$2")
The point is that without quotes readlink removes backslashes which escape whitespaces. Compare three results:
1. Without backslashes and quotes readlink -f assumes that there are three different files/directories (with default path in current directory) and produces
$ readlink -f /tmp/My Example Directory
/tmp/My
/home/jimmij/Example
/home/jimmij/Directory
2. With escaping backslashes but without quotes readlink -f understands that there is only one directory, but removes backslashes from output, so that somecommand takes three separate arguments
$ readlink -f /tmp/My\ Example\ Directory
/tmp/My Example Directory
3. With backslashes and with double-quotes readlink -f gives the output with backslashes what is (most probably) expected by somecommand
$ readlink -f "/tmp/My\ Example\ Directory"
/tmp/My\ Example\ Directory
BTW, as a rule of thumb: if there are any problems with whitespaces in the shell-like scripts (bash, zsh, whatever) the first thing to play with is different quotation marks around variables.
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 //')