I have a text file like so:
every- 100
atmo- 220
I wish to replace character before - with *. So the expected output should be
*****- 100
****- 220
How would I do that using sed?
I have tried using s/[a-z]*-/*/g but it does not work and replaces before and including the - with a single *
How do I fix this?
Implement a loop using labels and branching:
$ sed ':1; s/^\(\**\)[a-z]/\1*/; t1' <<EOF
every- 100
atmo- 220
EOF
*****- 100
****- 220
With Perl:
perl -pe 's/.(?=.*-)/*/g' file
Output:
*****- 100
****- 220
Derived from https://stackoverflow.com/a/57458869/3776858
With GNU awk. Use - as input and output field separator and replace in first column everything with *.
gawk 'BEGIN{FS=OFS="-"} gsub(/./,"*",$1)' file
Output:
*****- 100
****- 220
Another way of coding it in sed:
$ sed ':loop ; /[^*]-/s/[^*]/*/ ; t loop' <<END
every- 100
atmo- 220
END
*****- 100
****- 220
And an alternative coding in Perl:
perl -pe 's/[^*]/*/ while /[^*]-/'
This might work for you (GNU sed):
sed 's/-/\n/;h;s/[^\n]/*/g;G;s/\n.*\n/-/' file
This uses a newline as a delimiter and a copy to achieve the required result
Replace the - by a newline.
Copy the line.
Replace everything except the newline by *'s.
Append the copy.
Replace everything between the newlines by a single -.
An alternative, using a loop:
sed ':a;s/^\(\**\)[^-*]/\1*/;ta' file
Related
I have a file which contains the following records
+aaaa
+bbbb
cccc-123
-dddd
eeee+789
-fff+456
ggg
Now I want to keep only the records if the first character is a "+" or "-" sign
so the (new) file should look like this
+aaaa
+bbbb
-dddd
-fff+456
Can this be done via a grep or sed command ?
Try this:
grep '^\[+-\]' myfile.txt
or
grep '^[+-]' myfile.txt
Depending on your flavour of grep
This might work for you (GNU sed):
sed '/^[+-]/!d' file
or:
sed -n '/^[+-]/p' file
In the first solution: if the first character of the line is not + or - delete the line.
In the second solution: if the first character of the line is + or - print it.
sed -i 's/$/\'/g'
sed -i "s/$/\'/g"
How to escape both $ and ' by 1 command?
This might work for you (GNU sed):
sed 's/$/'\''/' file
Adds a single quote to the end of a line.
sed 's/\$/'\''/' file
Replaces a $ by a single quote.
sed 's/\$$/'\''/' file
Replaces a $ at the end of line by a single quote.
N.B. Surrounding sed commands by double quotes is fine for some interpolation but may return unexpected results.
Use octal values
sed 's/$/\o47/'
Care to use backslash + letter o minus + octal number 1 to 3 digit
Just don't use single quotes to start the sed script?
sed "s/$/'/"
The /g at the end means to apply everywhere it's found on each stream (line) - you don't need this since $ is a special character indicating end of stream.
To add a quote at the end of a line use
sed -i "s/$/'/g" file
sed -i 's/$/'"'"'/g' file
See proof.
If there are already single quotes, and you want to make sure there is single occurrence at the end of string use
sed -i "s/'*$/'/g" file
sed -i 's/'"'*"'$/'"'"'/g' file
See this proof.
To escape $ and ' chars use
sed -i "s/[\$']/\\\\&/g" file
See proof
[\$'] - matches $ (escaped as in double quotes it can be treated as a variable interpolation char) or '
\\\\& - a backslash (need 4, that is literal 2 backslashes, it is special in the replacement), and & is the whole match.
I want sed command to delete a line from which which contain more than 10 number and which are not start with 91
My file content is like this
919876543210
789876543210
9012345678
12345678901
9865746321
And need output like this.
919876543210
9012345678
9865746321
I have tried awk 'length>=4' 1.txt | grep -v ^91
this will show me
789876543210
12345678901
What you can do:
ignore all lines starting with "91", /^91/!
otherwise delete anything with at least 11 characters
(assuming you do not care about the difference between digits, letters, whitespace...),
{/.........../d}
Altogether:
sed '/^91/!{/.........../d}'
With the -E it would be more elegantly possible.
(My sed is GNU sed version 4.2.1)
Simple, clear, portable, efficient, etc. with awk:
$ awk '/^91/ || length()<11' file
919876543210
9012345678
9865746321
I have function that prints a header that needs to be applied across several files, but if I utilize a sed process substitution the lines prior to the last have a backslash \ on them.
E.g.
function print_header() {
cat << EOF
-------------------------------------------------------------------
$(date '+%B %d, %Y # ~ %r') ID:$(echo $RANDOM)
EOF
}
If I then take a file such as test.txt:
line 1
line 2
line 3
line 4
line 5
sed "1 i $(print_header | sed 's/$/\\/g')" test.txt
I get:
-------------------------------------------------------------------\
November 24, 2015 # ~ 11:18:28 AM ID:13187
line 1
line 2
line 3
line 4
line 5
Notice the troublesome backslash at the end of the first line, I'd like to not have that backslash appear. Any ideas?
I would use cat for that:
cat <(print_header) file > file_with_header
This behavior depends on the sed dialect. Unfortunately, it's one of the things which depends on which version you have.
To simplify debugging, try specifying verbatim text. Here's one from a Debian system.
vnix$ sed '1i\
> foo\
> bar' <<':'
> hello
> goodbye
> :
foo
bar
hello
goodbye
Your diagnostics appear to indicate that your sed dialect does not in fact require the backslash after the first i.
Since you are generating the contents of the header programmatically anyway, my recommended solution would be to refactor the code so that you can avoid this conundrum. If you don't want cat <<EOF test.txt then maybe experiment with sed 1r/dev/stdin' <<EOF test.txt (I could not get 1r- to work, but /dev/stdin should be portable to any Linux.)
Here is my kludgy fix, if you can find something more elegant I'll gladly credit you:
sed "1 i $(print_header | sed 's/$/\\/g;$s/$/\x01/')" test.txt | tr -d '\001'
This puts an unprintable SOH (\x01) ascii Start Of Header character after the inserted text, that precludes the backslashes and then I run it over tr to delete the SOH chars.
I'm using CMD on Windows Xp to replace special text with Sed. I'm using this command for replace special characters like $ or * :
sed -i "s/\*/123/g;" 1.txt
the previous command does not work because i have \, " and other special strings that sed use to make regex. The escape character ^ doesn't work well because sed no give me error but nothing change inside files.
To change this text "{\*)(//123/$$ i try use this command:
sed -i "s£"^"{^\^*)(//123/^$^$"£xx£g;" 1.txt £ is the delimiter, xx is new text..but nothing change
How i want to turn text like this? sed -i^/\\*$/$[{" ;" 1.txt into xx
This might work for you:
echo '"{\*)(//123/$$' | sed "s/[\"][{][\\][*][)][(][/][/]123[/][$][$]/xx/"
xx