I'm trying to replace a number in a file using sed. This number can be found using \b<NUMBER>\b. However, there are comments in the file I'm parsing that sometimes have the same number and I would like to leave them unchanged.
All the lines that need to be replaced are similar to:
some_text <1 4 35 314 359>
And the complete file could be something like:
# This is not to be replaced: 314
some_text <1 4 35 314 359>
So, if I wanted to replace 314, how could I do it with sed?
I can find it with the following grep:
grep -P "^[^#].*some_text <[ 0-9]*>" "<FILE>" | grep -e "\b314\b")
But I can't seem to figure out a way to do it with sed. The old line I had would replace all the entries for that number:
sed -i "s/\b *314\b//" <FILE>
Any clarifications or help would be most welcome!
Thank you for your help!
/G
You can use sed like this:
sed '/some_text/s/\b314\b/789/' file
# This is not to be replaced: 314
some_text <1 4 35 789 359>
You could use awk instead, skipping any lines that are comments:
awk '!/^#/{sub(/\y314\y/,789)}1' file
As you've used word boundaries in your example, I'm assuming that you have GNU awk installed and I've used \y, which is a word boundary.
Related
I have a text file containing :
A 25 27 50
B 35 75
C 75 78
D 99 88 76
I wanted to delete the line that does not have the fourth field(the fourth pair of digits).
Expected output :
A 25 27 50
D 99 88 76
I know that awk command would be the best option for such task, but i'm wondering what's the problem with my sed command since it should work as you can see below :
sed -E '/^[ABCD] ([0-9][0-9]) \1$/d' text.txt
Using POSIX ERE with back-referencing (\1) to refer to the previous pattern surrounded with parenthesis.
I have tried this command instead :
sed -E '/^[ABCD] ([0-9][0-9]) [0-9][0-9]$/d' text.txt
But it seems to delete only the first occurrence of what i want.
I would appreciate further explanation of,
why the back-referencing doesn't work as expected.
what's the matter with the first occurrence in the second attempt,should i included global option if yes then how, since i already tried adding it at the end along side with /d (for delete) but it didn't work .
Much much easier with awk:
awk 'NF == 4' file
A 25 27 50
D 99 88 76
This awk command uses default field separator of space or tab and checks a condition NF == 4 to make sure we print lines with 4 fields only.
With sed it would be (assuming no leading+trailing spaces in each line):
sed -nE '/^[^[:blank:]]+([[:blank:]]+[^[:blank:]]+){3}$/p' file
A 25 27 50
D 99 88 76
With your shown samples in sed program you could try following. Written and tested in GNU sed.
sed -nE '/^([^[:space:]]+[[:space:]]+){3}[^[:space:]]+$/p' Input_file
Explanation: Simply stopping the printing for lines by sed's -n option. Then using -E for using ERE in program. In main program using regex to match from starting non-space(1 or more occurrences) followed by spaces(1 or more occurrences) and this combo 3 times(to match 3 fields basically) which is followed by non spaces 1 or more occurrences till end of line's value, if this regex matched then print that line.
This might work for you (GNU sed):
sed -En 's/\S+/&/4p' file
Turn off implicit printing -n and on extended regexp -E.
Substitute the 4th field with itself and print the result.
I'm trying to remove amazon and downloadAll.sh from output.
Any thoughts on what I'm doing wrong?
❯ ls | sed 's/[^0-9]{1,4}//'
downloadAll.sh
1041
973
295
127
273
221
1010
1152
227
937
994
210
572
1091
323
1328
472
1710
1192
1629
957
1167
1120
1628
1597
amazon
You can use find with a regex:
find . -regextype posix-egrep -regex '.*/[0-9]{1,4}'
Details:
. - search in the current directory
-regextype posix-egrep - the regex engine is set to egrep, POSIX ERE (we can use {min,max} quantifier then with no extra escaping)
-regex '.*/[0-9]{1,4}' - the filenames fully matching the regex will get returned. The .*/[0-9]{1,4} pattern matches anything followed with / + one to four digits till the end of string.
To list files/directories ending with a digit use:
printf '%s\n' *[0-9]
To list files/directories NOT ending with a digit use:
printf '%s\n' *[!0-9]
# digits.sh
find \
./ ` # search in current directory` \
-maxdepth 1 ` # don't search recursively` \
| sed 's/.*[^0-9]$//g' ` # remove any file that doesn't end in a digit`
❯ bash digits.sh
./1328
./1091
./957
./1010
./210
./937
./295
./1597
./1629
./973
./1041
./323
./1192
./1167
./1710
./221
./42
./572
./127
./1628
./472
./1120
./227
./1152
./994
./273
./46
You are using an Extended Regular Expression (ERE) while sed is interpreting the script as a Basic Regular Expression (BSE), here is the GNU sed manual's take on it. Either convert to BSE or add the -E switch to the sed command for ERE interpretation.
However, for this simple task, grep is sufficient:
grep -x '[0-9]\+'
This might work for you (GNU sed):
sed -E '/^[0-9]{1,4}$/!s/.*//' file
If a line does not contain 1 to 4 digits, replace it by nothing.
N.B. This will return a blank line for any line that does not meet the required criteria.
Perhaps what you really want is to delete such lines?
sed -E '/^[0-9]{1,4}$/!d' file
Of course to list 1 to 4 digit files can be achieved like so:
ls [0-9] [0-9][0-9] [0-9][0-9][0-9] [0-9][0-9][0-9][0-9]
I would like to replace the empty space between each and every field with comma delimiter.Could someone let me know how can I do this.I tried the below command but it doesn't work.thanks.
My command:
:%s//,/
53 51097 310780 1
56 260 1925 1
68 51282 278770 1
77 46903 281485 1
82 475 2600 1
84 433 3395 1
96 212 1545 1
163 373819 1006375 1
204 36917 117195 1
If you are talking about sed, this works:
sed -e "s/ /,/g" < a.txt
In vim, use same regex to replace:
s/ /,/g
Inside vim, you want to type when in normal (command) mode:
:%s/ /,/g
On the terminal prompt, you can use sed to perform this on a file:
sed -i 's/\ /,/g' input_file
Note: the -i option to sed means "in-place edit", as in that it will modify the input file.
I know it's not exactly what you're asking, but, for replacing a comma with a newline, this works great:
tr , '\n' < file
Try the following command and it should work out for you.
sed "s/\s/,/g" orignalFive.csv > editedFinal.csv
IF your data includes an arbitrary sequence of blank characters (tab, space), and you want to replace each sequence with one comma, use the following:
sed 's/[\t ]+/,/g' input_file
or
sed -r 's/[[:blank:]]+/,/g' input_file
If you want to replace sequence of space characters, which includes other characters such as carriage return and backspace, etc, then use the following:
sed -r 's/[[:space:]]+/,/g' input_file
If you want the output on terminal then,
$sed 's/ /,/g' filename.txt
But if you want to edit the file itself i.e. if you want to replace space with the comma in the file then,
$sed -i 's/ /,/g' filename.txt
I just confirmed that:
cat file.txt | sed "s/\s/,/g"
successfully replaces spaces with commas in Cygwin terminals (mintty 2.9.0). None of the other samples worked for me.
On Linux use below to test (it would replace the whitespaces with comma)
sed 's/\s/,/g' /tmp/test.txt | head
later you can take the output into the file using below command:
sed 's/\s/,/g' /tmp/test.txt > /tmp/test_final.txt
PS: test is the file which you want to use
Can I increase some numbers in txt files with grep/sed?
I want to find all numbers in file and increase them for 5. Is that possible with grep and sed or I need to write app for that?
EDIT:
File has n lines which begin with number - number and than some text.
Like title for movie.
example line:
34 - 36 : Some text.
You can use perl as:
perl -i -pe 's/(\d+)/$1+5/eg' filename
See it
Probably awk. Change the record separator to whitespace (assuming this is what you want to do), then if a record matches the regex ^[0-9]*$ convert to number add 5 and print, otherwise print.
This is a pretty complete solution but "left as exercise" to code up.
I believe you should use awk Changing the Contents of a Field
>cat 1.txt
34 - 36 : Some text.
cat 1.txt | awk '{ $1=$1+5; $3=$3+5; print $0; }'
39 - 41 : Some text.
This might work for you (GNU sed & Bash):
sed 's/[0-9]\+/$((&+5))/g;s/.*/echo "&"/e' file
How could I use sed to find all lines that don't have exactly 35 occurrences of the "|" character?
If I can't use sed, what could I use?
I'd use awk as it's more readable and doesn't involve nasty regular expression syntax:
awk -F'|' 'NF != 36' filename
Or grep:
grep -v '^\([^|]*|\)\{35\}[^|]*$' filename
But if you want to use sed:
sed '/^\([^|]*|\)\{35\}[^|]*$/d' filename
Here's something you could try:
perl -ne 'print unless (split(/|/, $_)==36);' your_input_file
Splits each line at | and counts the number of resulting parts. If there are 36, you've got 35 | and the line is not printed. Otherwise, the line is printed.