Substitution option: s in sed command [duplicate] - sed

This question already has answers here:
How to use sed to replace only the first occurrence in a file?
(25 answers)
Closed 8 years ago.
I am using sed command make substitution in the file.
Assume my file1 is:
10
11
10
11
Then I want to substitute the 1st "10" in file1 to "12", and dump to file2. The file2 should be:
12
11
10
11
I tried this command:
sed 's/10/12/' file1 >file2
But it changed the 2nd "10" also. So, how can I write the sed command to do that?

If you can use awk instead of sed, you can have more control like this:
awk '!changed && /10/ { sub(/10/, "12"); changed = 1}1' file1
12
11
10
11

try:
sed '0,/10/s/10/12/' file1 >file2

Like GriffinG said, you can do something like this:
sed '0,/10/ s/10/12/' file1 > file2
The 0,/10/ at the beginning sets the bounds on the following substitution command. It says start from line 0 (the first line), and go until a line it matches the pattern /10/. So After that first match, sed will stop processing that substitution.

If you do not have GNU sed, try:
echo | cat - file | sed '1,/10/s/10/12/; 1d'
or
sed '1,/10/s/10/12/; 1d' << EOF
$(cat file)
EOF
or in bash / ksh93
sed '1,/10/s/10/12/; 1d' <(echo; cat file)
GNU sed knows 0,/10/ so the extra empty line is not required

Related

sed: -e expression #1, char 5: unterminated `s' command [duplicate]

This question already has answers here:
sed edit file in place
(15 answers)
Closed 4 years ago.
I'm learning SED and I saw this sed substitution example. It's supposed to replace the first lowercase t as uppercase in each new line.:
$ sed 's/t/T' text-01.txt
sed: -e expression #1, char 5: unterminated `s' command
Contents of file:
$ cat text-01.txt
10 tiny toes
this is that
5 funny 0
one two three
tree twice
It's not the end of the world though, since I can just output into a new file:
cat text-01.txt | sed 's/t/T/' > text-02.txt
But what am I supposed to do if I want to edit the original file?
The commands aren't the same, the closing / is missing in the first one:
# v
sed 's/t/T' text-01.txt
cat text-01.txt | sed 's/t/T/' > text-02.txt
# ^

sed command to delete a line with contain more than 10 character which not start with 91

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

Sed Process Substitution on Insert - Without Backslashes

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.

Sed (POSIX) coming from linux [duplicate]

This question already has answers here:
How to remove every other line with sed?
(5 answers)
Closed 8 years ago.
I am somewhat new to posix, and i can't use: sed '1~2p'
My goal is to skip every one line from line 1:
1
2
3
4
would become
1
3
I was wondering what is the posix equivalent of ~.
Code for sed:
sed -e n -e d file
or:
sed -e 'n;d' file
The simpler, portable solution would be:
awk 'NR%2' file
bash solution:
while read -r line; do
[ $((i++ % 2)) -eq 0 ] && echo "$line";
done < file

Delete first and last line or record from file using sed

I want to delete first and last line from the file
file1 code :
H|ACCT|XEC|1|TEMP|20130215035845|
849002|48|1208004|1
849007|28|1208004|1
T|2
After delete the output should be
849002|48|1208004|1
849007|28|1208004|1
I have tried below method but has to run it 2 times, I want one liner solution to remove both in one go!
sed '1,1d' file1.txt >> file1.out
sed '$d' file1.out >> file2
Please suggest one liner code....
You could use ;
sed '1d; $d' file
Use Command Separator
In sed, you can separate commands using a semicolon. For example:
sed '1d; $d' /path/to/file
How about:
sed '$d' < file1.txt | sed "1d"
Try sed -i '1d;$d' /path/to/file
awk 'NR>2{print v}{v=$0}'
Starting with line 3, print the previous line each time. This means the first and last lines will not be printed.