Substitute all occurrences of n spaces with a single character - sed

I would like to use sed (is this the best tool?) to go from this:
foo bar buzz fuzz
to this:
foo|bar|buzz|fuzz
How can this be done ?
Many thanks :).

$ sed 's/\s\s*/|/g' < input

Assuming you have 5 spaces between your items and they are in a file called test.txt:
sed -i "s/ /|/g" test

Use the [:SPACE:] POSIX Class
If the number of spaces could change, or might be a mix of spaces and tabs, then you want to use a POSIX class to replace a series of whitespace characters with a single pipe symbol globally within the current pattern space. For example:
$ echo 'foo bar buzz fuzz' | sed 's/[[:space:]]\+/|/g'
foo|bar|buzz|fuzz

If you have GNU sed:
sed -r 's/ +/|/g'

Related

How to replace next word after a match in perl or sed expression?

I'm trying to replace doxygen comment from a file with swift comments.
e.g: /// \param foo should became /// - Parameter foo: with foo
So far I have
gsed -i 's/\\param/\- Parameter/g' my_file or perl -pe 's/\\param/\- Parameter/g'
I'd like to replace the following word (foo) after my expression with word: (foo:)
I didn't manage to find a good expression for that. Ideally, something that work on Linux and macOS
In perl you can capture and put back the word with $1 (first parentheses).
s/\\param\s+(.+)/- Parameter $1:/g
.+ will capture the rest of that line. If that is something you don't want, and just want to capture the first word, you can use \S+ or \w+ or whatever other character class that matches the characters you want to capture, e.g. [a-z_-]+.
In sed it is probably \1.
Using sed
$ sed -E 's/\\(param)( [^ ]*)/- \u\1eter\2:/' input_file
/// - Parameter foo:
You could use pattern with a single capture group, and use that group with \1 in the replacement.
sed -E 's/\\param[[:space:]]+([^[:space:]]+)/- Parameter \1:/g' my_file
The pattern matches:
\\param Match \param
[[:space:]]+ Match 1+ spaces
([^[:space:]]+) Capture group 1, match 1+ non whitespace chars
Output
- Parameter foo:
If you validated the output, then you can change sed -E to sed -Ei to do the replacement.

Replace variable num in double quotes - SED

I have a line like this:
"abc/x-y-z": "^1.4"
I need to replace ^1.4with * in the same file such that the output is "abc/x-y-z": "*"
The num inside the double quotes could be any variable number.
I tried this but it is highly specific to ^1.4 number:
sed -i '21s/^1.4/*/' abc.json
With your shown samples, please try following. You need to escape ^ here to make it literal character and you need to escape . dot as well to make it treat as literal character.
sed 's/\^1\.4/*/' Input_file
OR as per OP's comment to make it dynamic try:
sed 's/\^[0-9]+\.[0-9]+/*/' Input_file
Also if you are performing it on 21st line of your file then use 21s like you tried in your attempt. This code will substitute only very 1st occurrence of ^1.4 here in case you want to substitute all occurrences then use g(globally substitution) option for above code.
I have not used -i option(to do inplace update into Input_file itself) once you are happy with results then use sed -i option in above code.
When making changes to files, I prefer the file editor ed to the stream editor sed (ed is standard, sed -i isn't, and different versions have different quirks that bite people here on a regular basis).
ed -s input.txt <<EOF
21s/"^[[:digit:]]\{1,\}\(\.[[:digit:]]\{1,\}\)\{0,1\}"/"*"/
w
EOF
On line 21, matches a quote followed by a carat followed by 1 or more digits, optionally followed by a period and another sequence of 1 or more digits and finally the trailing quote character. All that is replaced by "*", and finally the changed file is written back to disk.
Posix BREs are a pain, no? GNU ed 1.17 and newer, and NetBSD ed can take EREs instead:
ed -Es input.txt <<EOF
21s/"\^[[:digit:]]+(\.[[:digit:]]+)?"/"*"/
w
EOF
which is a lot easier to read.

Matching strings even if they start with white spaces in SED

I'm having issues matching strings even if they start with any number of white spaces. It's been very little time since I started using regular expressions, so I need some help
Here is an example. I have a file (file.txt) that contains two lines
#String1='Test One'
String1='Test Two'
Im trying to change the value for the second line, without affecting line 1 so I used this
sed -i "s|String1=.*$|String1='Test Three'|g"
This changes the values for both lines. How can I make sed change only the value of the second string?
Thank you
With gnu sed, you match spaces using \s, while other sed implementations usually work with the [[:space:]] character class. So, pick one of these:
sed 's/^\s*AWord/AnotherWord/'
sed 's/^[[:space:]]*AWord/AnotherWord/'
Since you're using -i, I assume GNU sed. Either way, you probably shouldn't retype your word, as that introduces the chance of a typo. I'd go with:
sed -i "s/^\(\s*String1=\).*/\1'New Value'/" file
Move the \s* outside of the parens if you don't want to preserve the leading whitespace.
There are a couple of solutions you could use to go about your problem
If you want to ignore lines that begin with a comment character such as '#' you could use something like this:
sed -i "/^\s*#/! s|String1=.*$|String1='Test Three'|g" file.txt
which will only operate on lines that do not match the regular expression /.../! that begins ^ with optional whiltespace\s* followed by an octothorp #
The other option is to include the characters before 'String' as part of the substitution. Doing it this way means you'll need to capture \(...\) the group to include it in the output with \1
sed -i "s|^\(\s*\)String1=.*$|\1String1='Test Four'|g" file.txt
With GNU sed, try:
sed -i "s|^\s*String1=.*$|String1='Test Three'|" file
or
sed -i "/^\s*String1=/s/=.*/='Test Three'/" file
Using awk you could do:
awk '/String1/ && f++ {$2="Test Three"}1' FS=\' OFS=\' file
#String1='Test One'
String1='Test Three'
It will ignore first hits of string1 since f is not true.

using sed to remove special chars and add spaces instead

I have a block of text i'd like to change up:
^#^A^#jfits^#^A^#pin^#^A^#sadface^#^A^#secret^#^A^#test^#^A^#tools^#^A^#ttttfft^#^A^#tty^#^A^#vuln^#^A^#yes^#^
using sed i'd like to remove all the ^#^A^ (and variations of those chars) with a few spaces.
I tried:
cat -A file | sed 's/\^A\^\#/ /'
but thats obviously wrong, can someone help?
if you can enumerate the allowed characters then you can do something like
sed -e 's/[^a-zA-Z0-9]/ /g'
which will replace everything not in the set of alphanumeric characters with a space.
If you just want to replace all 'non-printable' characters with spaces then you can use a character class[1] with
sed -e 's/[^[:print:]]/ /g'
some older versions of sed may not support this syntax though but it is standardized in the unix specification so you should not feel guilty for using it.[2]
[1] http://sed.sourceforge.net/sedfaq3.html
[2] http://pubs.opengroup.org/onlinepubs/009695399/basedefs/xbd_chap09.html#tag_09_03
It looks like ^A is not two characters, but in fact just one control character. So you should write something like \x01 instead.
Anyway, there are three character ranges, \x00-\x1f are control characters, \x20-\x7f are ascii, and others are... something that depends on encoding.
I don't know sed well, but if you want ascii only, that's how I would've done it in perl:
head /dev/urandom | perl -pe 's/[^\x20-\x7f]/ /gi'
If only replace ^A and ^#, you can use this:
sed 's/[\x01\x0]/ /g' file
Then I find more similar answers in SO which already discussed.
https://superuser.com/questions/75130/how-to-remove-this-symbol-with-vim
Replacing Control Character in sed

Remove a hyphen from a specific line in a file

I have a data file that needs to have several uniq identifiers stripped of hyphens.
So I have:
(Special_Section "data-values")
and I want to have it replaced with:
(Special_Section "datavalues")
I wanted to use a simple sed find/replace, but the data and values are different each time. Preferably, I'd run this in-place since the file has a lot of other information I want to keep in tact.
Does sed or awk have a way to remove the hyphen from the matched portion only?
Currently I can match with: sed -i 's/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/&/g *myfiles*
But I would like to then run s/-// on & if it's possible.
You seems to be using GNU sed, so something like this might work:
sed -ri '
s/(Special_Section [^-]*)-([^)]*)/\1\2/g
' <your_filename_glob>
does this work?
sed -i '/(Special_Section ".*-.*")/{s/-//}' yourFile
Close - scan for the lines and then substitute on those that match:
sed -i '/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/s/\( "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*\)"/\1\2/' *myfiles*
You can split that over several lines to avoid the scroll bar in SO:
sed -i '/Special_Section "[a-zA-Z0-9]*-[a-zA-Z0-9]*"/{
s/\( "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*\)"/\1\2/
}' *myfiles*
And on further thoughts, you can also do:
sed -i 's/\(Special_Section "[a-zA-Z0-9]*\)-\([a-zA-Z0-9]*"\)/\1\2/' *myfiles*
This is more compact. You can add the g qualifier if you need it. Both solutions use the special \(...\) notation to capture parts of the regular expression.