Command sed using g - linux

I am new to Linux.
I was debugging some code. I encountered the following command:
PROGRAM_ID=$(echo $PROGRAM_ID|sed 's/-/,/g')
Can anybody explain what the g represents here?
I understand hyphen is being replaced with comma.

The /g flag means, perform the substitution globally on a line. Without that flag, only the first hyphen on every line would get substituted.
A better way with Bash would be
PROGRAM_ID=${PROGRAM_ID//-/,}
but if you have to be portable to Bourne shell in general, this replacement facility is not available.
(In which case you should take care to keep "$PROGRAM_ID" in double quotes in the echo.)

Its easy to see how g (global) works with these two example:
echo "test-one-two-three" | sed 's/-/,/g'
test,one,two,three
echo "test-one-two-three" | sed 's/-/,/'
test,one-two-three
Without the g it only replace the first hit.

Related

vim - why will search find it but search and replace not? (this escaped special char pattern)

want to search and replace in vim, the /find finds the pattern but :s%//g will not?
have a script that monitors software raid (if interested check it out https://dwaves.org/2019/09/06/linux-server-monitor-software-raid-mail-notification-on-failure/)
echo "=== smart status of all drives ==="| tee -a /scripts/monitor/raid_status_mail.log
# want to search and replace the /path/to/file.sh with $LOGFILE
# searching for the pattern works like charm
/\/scripts\/monitor\/raid_status_mail.log
# but replacing it won't
:s%/\/scripts\/monitor\/raid_status_mail\.log/\$LOGFILE/g
# what does one do wrong?
should replace /scripts/monitor/raid_status_mail.log with $LOGFILE
The substitution operation needs to be prefixed with %s and not the other way around as s%. So doing
%s/\/scripts\/monitor\/raid_status_mail\.log/\$LOGFILE/g
should work as expected. Or just the Vim's equivalent ex in command line mode as
printf '%s\n' "%s/\/scripts\/monitor\/raid_status_mail\.log/\$LOGFILE/g" w q | ex -s file
You inverted the beginning s%. Use %s instead.
Also, you use / as separation for the different fields, it works but makes the command less readable. You can replace the separation character by anything else. You could use : for example:
%s:/scripts/monitor/raid_status_mail.log:$LOGFILE:g
One last tip: install vim-over
This will highlight your searches in live while replacing something in vim.

Executing error while executing sed command

Below given sed command is working fine on online BASH & KSH shell, but getting an error "Illegal operation --r" while trying to run it on linux server.
I'm trying to make a regex to parse MFBBMYKLAXXX from first line.
echo "{1:F01MFBBMYKLAXXX2474811384}{2:O3001434181108BKKBTHBKBXXX12203020241811081534N}{3:{108:241C182AFFD4403C}}{4:
:15A:
:20:10168957
:22A:NEWT
:94A:BILA
:22C:BKKBBK8308MFBBKL
:82A:BKKBTHBK
:87A:MFBBMYKL
:15B:
:30T:20181108
:30V:20181109
:36:32,8308
:32B:THB2500000,
:53A:/610165
BKKBTHBK
:57A:BKKBTHBK
:33B:USD76148,01
:53A:CHASUS33
:57A:/04058664
BKTRUS33
:58A:MFBBMYKL
:15C:
:24D:ELEC/REUTERS D-3000
-}{5:{CHK:4117CD0206B7}}{S:{COP:S}}
" | sed -rn 's/.*\{1:F01([A-Z]{12}).*/\1/p'
The use of sed -r (or in some dialects sed -E) is nonstandard and optional.
It selects a regex dialect called extended regular expressions, which allows you to express some things more succinctly.
POSIX basic regular expressions support pretty much the same facilities, but with an oddball syntax where you have to backslash some characters to obtain their special meaning (which in other words does exactly the opposite of what backslash escaping originally did).
So if you have an extended regular expression like a+(b{2})c then if your sed does not support either -r or -E, try a\+\(b\{2\}\}c without any special option, and hope that your sed is at least roughly on par with what POSIX specifies. (If you're serious about retrocomputing, this is unlikely, though.)
The original regular expression implementation by Ken Thompson only supported the regex metacharacters [...] and . and *, and for a long time, that's all sed supported, too.
Of course, you could always install a more modern sed. I know SunOS used to have some goodies in their xpg4 directory but I have no idea if this was is the case in Solaris; if so, maybe you just need to add /usr/xpg4/bin to your PATH. (According to this it was true at one point in time at least.)

Understanding sed

I am trying to understand how
sed 's/\^\[/\o33/g;s/\[1G\[/\[27G\[/' /var/log/boot
worked and what the pieces mean. The man page I read just confused me more and I tried the info sai Id but had no idea how to work it! I'm pretty new to Linux. Debian is my first distro but seemed like a rather logical place to start as it is a root of many others and has been around a while so probably is doing stuff well and fairly standardized. I am running Wheezy 64 bit as fyi if needed.
The sed command is a stream editor, reading its file (or STDIN) for input, applying commands to the input, and presenting the results (if any) to the output (STDOUT).
The general syntax for sed is
sed [OPTIONS] COMMAND FILE
In the shell command you gave:
sed 's/\^\[/\o33/g;s/\[1G\[/\[27G\[/' /var/log/boot
the sed command is s/\^\[/\o33/g;s/\[1G\[/\[27G\[/' and /var/log/boot is the file.
The given sed command is actually two separate commands:
s/\^\[/\o33/g
s/\[1G\[/\[27G\[/
The intent of #1, the s (substitute) command, is to replace all occurrences of '^[' with an octal value of 033 (the ESC character). However, there is a mistake in this sed command. The proper bash syntax for an escaped octal code is \nnn, so the proper way for this sed command to have been written is:
s/\^\[/\033/g
Notice the trailing g after the replacement string? It means to perform a global replacement; without it, only the first occurrence would be changed.
The purpose of #2 is to replace all occurrences of the string \[1G\[ with \[27G\[. However, this command also has a mistake: a trailing g is needed to cause a global replacement. So, this second command needs to be written like this:
s/\[1G\[/\[27G\[/g
Finally, putting all this together, the two sed commands are applied across the contents of the /var/log/boot file, where the output has had all occurrences of ^[ converted into \033, and the strings \[1G\[ have been converted to \[27G\[.

Is there different between single quote and double quote in vim command mode?

In my vim, I can use :%!sed "s/^/ /", got the wrong output when I use :%!sed 's/^/ /' .
sed: -e expression #1, char 0: no previous regular expression
Is there differences between single quote and double quote in vim command mode?
In my sed, single quote is the same as double quote.
$ echo "wha012" | sed 's/w/haha/'
hahaha012
$ echo "wha012" | sed "s/w/haha/"
hahaha012
my system is xp+vim 7.3 for windows.
In my system:
[1] "c://cygwin/bin/ash.exe"
[2] "c://cygwin/bin/bash.exe"
[3] "c://cygwin/bin/dash.exe"
[4] "c://cygwin/bin/sh.exe"
if i set set shell=\"c:\cygwin\bin\sh.exe"\ -f in _vimrc,i get the new wrong messages:
sed command can not found.
Funny, when I try :%!sed "/^/ /" I get the same error message as when I use single quotes:
sed: 1: "/^/ /": invalid command code /
(This line replaces the content of my file.) I expect to get an error message there because, as #Birei pointed out, you left out the sed s command. This works as expected, with either single or double quotes:
:%!sed "s/^/ /"
#Birei is also right that you can use vim to do things like this, but I assume you have simplified the example from what you were really trying to do.
To answer the original question, Vim uses single quotes for literal strings. The only special character in a literal string is ' itself. Strings delimited with double quotes use \ to denote special character, such as `"\<Esc>".
:echo 'a''b' == "a'b"
:help expr-string
:help literal-string
my system is xp+vim 7.3 for windows
By default Vim uses cmd.exe to run :! commands on Windows, which behaves differently with regard to quoting from the POSIX shell that your s/w/haha/ examples suggest you've been testing with. Try something like
:set shell=\"C:\path\to\sh.exe\"\ -f
to tell it to use your POSIX shell instead. Or if you're using cygwin then try the cygwin version of vim instead of the Windows native one.
The difference is in the sed command, that lets interpolate variables when you execute it directly from the shell, like:
sed "s/$pattern/$replacement/"
but your problem is that you have to use a substitution command that begins with letter s, like:
:%!sed "s/^/ /"
Also you can have same behaviour inside vim without an external command, like:
:%s/^/ /

Using wildcards to exclude files with a certain suffix

I am experimenting with wildcards in bash and tried to list all the files that start with "xyz" but does not end with ".TXT" but getting incorrect results.
Here is the command that I tried:
$ ls -l xyz*[!\.TXT]
It is not listing the files with names "xyz" and "xyzTXT" that I have in my directory. However, it lists "xyz1", "xyz123".
It seems like adding [!\.TXT] after "xyz*" made the shell look for something that start with "xyz" and has at least one character after it.
Any ideas why it is happening and how to correct this command? I know it can be achieved using other commands but I am especially interested in knowing why it is failing and if it can done just using wildcards.
These commands will do what you want
shopt -s extglob
ls -l xyz!(*.TXT)
shopt -u extglob
The reason why your command doesn't work is beacause xyz*[!\.TXT] which is equivalent to xyz*[!\.TX] means xyz followed by any sequence of character (*) and finally a character in set {!,\,.,T,X} so matches 'xyzwhateveryouwant!' 'xyzwhateveryouwant\' 'xyzwhateveryouwant.' 'xyzwhateveryouwantT' 'xyzwhateveryouwantX'
EDIT: where whateveryouwant does not contain any of !\.TX
I don't think this is doable with only wildcards.
Your command isn't working because it means:
Match everything that has xyz followed by whatever you want and it must not end with sequent character: \, .,T and X. The second T doesn't count as far as what you have inside [] is read as a family of character and not as a string as you thought.
You don't either need to 'escape' . as long as it has no special meaning inside a wildcard.
At least, this is my knowledge of wildcards.

Resources