What does this SED command do and how can I modify it for my use case? - linux

I have been asked to fix someone else code so im unsure how the command actually works as ive never had to work with regex type code.
sed -r 's/([0-9]{2})\/([0-9]{2})\/([0-9]{4})\s([0-9]{2}:[0-9]{2}:[0-9]{2})/\3\/\1\/\2 \4/g'
This code reads the below txt file and is 'meant' to display the number in bold below.
placeholder_name 01/01/2022 12:00:00 01/01/2022 12:00:01 STATUS 12345/15 50
This is output to a new temp file but the issue is that only the first character in the number after the '/' is displayed, i.e. for the above example only 1 is displayed.
How would I modify the above command to take the full number after the '/'. Alternatively, if there is a nicer/better way to do this id be happy to hear it
Note: The number in bold has a range of 1-99

Using sed
$ sed -E 's#.*/([[:digit:]]+).*#\1#' input_file
15

Related

2g is not working in sed to skip the first occurrence of a match

I am trying to replace some text in a xml file using sed. I am able to replace my text, but i want to skip the first occurence. i am using 2g, but it is not working. No error is displayed, but no change happens to file.
My Xml file :
<file-min-size>10830</file-min-size>
<rotate-log>true</rotate-log>
<file-min-size>25600</file-min-size>
<rotate-log>true</rotate-log>
<file-min-size>32300</file-min-size>
<rotate-log>true</rotate-log>
<file-min-size>13456</file-min-size>
<rotate-log>true</rotate-log>
My expected output :
<file-min-size>10830</file-min-size>
<rotate-log>true</rotate-log>
<file-min-size>25600</file-min-size>
<rotate-log>true insertvalue</rotate-log>
<file-min-size>32300</file-min-size>
<rotate-log>true insertvalue</rotate-log>
<file-min-size>13456</file-min-size>
<rotate-log>true insertvalue</rotate-log>
I am using the below sed command.
sed -i 's#</rotate-log>#insertvalue</rotate-log>#2g' myfile.xml
The above command is not working. if i remove 2g, then the text is repalcing. i want to skip the first occurence. Any help ?
Also when i run the command second time, the values are entering again. Is there a way to check and replace only if not available ?
With GNU sed, you may use
sed -i '/<\/rotate-log>/{:A;n;s#</rotate-log># insertvalue</rotate-log>#;bA}' file
See the online sed demo
The command finds the line with </rotate-log> and then
:A - sets a label A
n - discards the current pattern space value and reads the next line into it
s#</rotate-log># insertvalue</rotate-log># - replaces </rotate-log> with # insertvalue</rotate-log>
bA - goes to A label (reads the next line, replaces, goes on).

How to change segments of lines in a file based on regex Linux

I have a file where each line begins with a specific logging info. Here is an example:
12-May 02:01:18:INFO:root:restapid=>someurlhere
12-May 02:01:19:INFO:root:response=>loremipsum
I want to catch these time info and replace it with the current date&time. I'am able to get the target part by using egrep but unfortunately I couldn't find a way to change it (It is probably because I'm not familiar with sed). How can I do that ? My egrep solution is the following:
egrep '^[0-9]+-[a-Z]+ [0-9]+:[0-9]+:[0-9]+'weblog.api
If I can manage this part, I want to assign this command to a function(or alias) in my bashrc and when I run it I want to change all the time info with current time by calling something like
sample_alias weblog.api
The desired output format is the following (Let's say right now time is 04 Feb 05:02:03. I believe I can get the time info by date "+%y%m%d%H%M" command)
05-Feb 05:02:03:INFO:root:restapid=>someurlhere
05-Feb 05:02:03:INFO:root:response=>loremipsum
cat v1
12-May 02:01:18:INFO:root:restapid=>someurlhere
12-May 02:01:19:INFO:root:response=>loremipsum
sed 's/[0-9]*-[a-Z]* [0-9]*:[0-9]*:[0-9]*/'"$(date +"%d-%b %H:%M:%S")"'/g' v1
05-Feb 06:21:30:INFO:root:restapid=>someurlhere
05-Feb 06:21:30:INFO:root:response=>loremipsum

How do I remove "X-TMASE-MatchedRID" key/value using "egrep -v"?

My file contains something like the below:
X-TM-AS-Product-Ver: IMSVA-8.2.0.1391-8.0.0.1202-22662.005
X-TM-AS-Result: No--0.364-7.0-31-10
X-imss-scan-details: No--0.364-7.0-31-10
X-TMASE-Version: IMSVA-8.2.0.1391-8.0.1202-22662.005
X-TMASE-Result: 10--0.363600-5.000000
X-TMASE-MatchedRID: 40jyuBT4FtykMGOaBzW2QbxygpRxo469FspPdEyOR1qJNv6smPBGj5g3
9Rgsjteo4vM1YF6AJbZcLc3sLtjOty5V0GTrwsKpl6V6bOpOzUAdzA5USlz33EYWGTXfmDJJ3Qf
wsVk0UbuGrPnef/I+eo9h73qb6JgVCR2fClyPE+EPh2lMKov3fdtvzshqXylpWZGeMhmJ7ScqBW
z6M5VHW/fngY5M/1HkzhvqqZL61o+ZdBoyruxjzQ==
This is my real text! I need to extract this line!
The existing code, written in the past by someone else, executes the below line:
cat $my_file | egrep -v "^(X-TM-AS)"
| egrep -v "X-imss-scan-details"
supposedly to remove all those key value lines which start with "X-".
The above piece of code has been working fine up until today because keys starting with X-TMASE has never been among the keys in the past. It has started to appear in the files today, and therefore it has caused the code to fail in extraction of the useful data.
Among the newly added keys, it seems to me that X-TMASE-MatchedRID is the one creating the headache for us, as it has a value which spans multiple lines:
X-TMASE-MatchedRID: 40jyuBT4FtykMGOaBzW2QbxygpRxo469FspPdEyOR1qJNv6smPBGj5g3
9Rgsjteo4vM1YF6AJbZcLc3sLtjOty5V0GTrwsKpl6V6bOpOzUAdzA5USlz33EYWGTXfmDJJ3Qf
wsVk0UbuGrPnef/I+eo9h73qb6JgVCR2fClyPE+EPh2lMKov3fdtvzshqXylpWZGeMhmJ7ScqBW
z6M5VHW/fngY5M/1HkzhvqqZL61o+ZdBoyruxjzQ==
Initially I tried the below:
cat $my_file | egrep -v "^(X-TM-AS)"
| egrep -v "X-imss-scan-details"
| egrep -v "^(X-TMASE-)"
But it didn't work. It didn't completely eliminate the value for X-TMASE-MatchedRID:
9Rgsjteo4vM1YF6AJbZcLc3sLtjOty5V0GTrwsKpl6V6bOpOzUAdzA5USlz33EYWGTXfmDJJ3Qf
wsVk0UbuGrPnef/I+eo9h73qb6JgVCR2fClyPE+EPh2lMKov3fdtvzshqXylpWZGeMhmJ7ScqBW
z6M5VHW/fngY5M/1HkzhvqqZL61o+ZdBoyruxjzQ==
This is my real text! I need to extract this line!
I wanted the output to be:
This is my real text! I need to extract this line!
That is, I don't want any metadata to be seen in the output.
Any idea how that can be achieved using egrep or any equivalent command?
If you just want to remove the first paragraph some other command is better, for example sed
sed '1,/^$/ d' "$my_file"

funky file name output from shell/bash?

So, im making a small script to do an entire task for me. The task is to get the output of the dmidecode -Fn into a text file and then take a part of the dmidecode output, in my example, the Address (0xE0000) as the file name of the txt.
My script goes as follows and does work, i have tested it. The only little issue that i have, is that the file name of the txt appears as "? 0xE0000.txt"
My question is, why am i getting a question mark followed by a space in the name?
#!/bin/bash
directory=$(pwd)
name=$(dmidecode|grep -i Address|sed 's/Address://')
inxi -Fn > $directory/"$name".txt
The quotes in the "$name".txt is to avoid an "ambiguous redirect" error i got when running the script.
Update #Just Somebody
root#server:/home/user/Desktop# dmidecode | sed -n 's/Address://p'
0xE0000
root#server:/home/user/Desktop#
Solution
The use of |sed -n 's/^.*Address:.*0x/0x/p' got rid of the "? " in 0xE0000.txt
A big thanks to everyone!
You've got a nonprinting char in there. Try:
dmidecode |grep -i Address|sed 's/Address://'| od -c
to see exactly what you're getting.
UPDATE: comments indicate there's a tab char in there that needs to be cleaned out.
UPDATE 2: the leading tab is before the word Address. Try:
name=$(dmidecode |grep -i Address|sed 's/^.*Address:.*0x/0x/')
or as #just_somebody points out:
name=$(dmidecode|sed -n 's/^.*Address:.*0x/0x/p')
UPDATE 3
This changes the substitution regex to replace
^ (start of line) followed by .* (any characters (including tab!)) followed by Address: followed by .* (any characters (including space!)) followed by 0x (which are always at the beginning of the address since it's in hex)
with
0x (because you want that as part of the result)
If you want to learn more, read about sed regular expressions and substitutions.

Linux rename function not being used correctly

I'm trying to use the rename command in a Terminal in Ubuntu to append a string to the beginning of some avi file names as follows.
rename -n 's/(\w)\.avi$/String_to_add__$1\.avi/' *.avi
So I expect the following:
String_to_add_MyMovie.avi
Problem is that when I run the command it appends the string to the end of the file name, so I end up with the following:
MyMovie_String_to_add_.avi
I'm not sure if I have the perlexpr syntax wrong or something else. Any insight is appreciated.
UPDATE:
Thanks for the suggestions, I tried the suggestions from alno and plundra and made the following modification:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
But now the file gets the string inserted in the middle of the name as follows:
My_String_to_add_Movie
My apologies though, I neglected to mention that the titles are preceded by 3 numeric values, so the file name nomenclature is {3 numbers}-My_Movie.avi so for example 001-My_Movie.avi. But I didn't think this would make a difference since I'm assuming \w+ matches alphanumeric characters, might the '-' be the issue?
Haven't tried Christian's approach yet, I want to be able to use the rename command, or at least understand why it's not working before I try a different approach.
I don't think rename -n is standard. You could do this:
for i in *.avi; do mv $i String_to_add_$i; done
You're only matching a single character with \w, you want \w+, so the complete line would be:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
Correct version:
rename -n 's/(\w+)\.avi$/String_to_add__$1\.avi/' *.avi
You simply forgot + after \w, so it tried to match only one character.

Resources