Pull a specific line from a man page for a given exit code with bash - linux

I'd like to return a specific line from the EXIT CODE section of a man page, given a valid exit code.
For example, if I run curl in a script and it returns an exit code of 2, I'd like to return the line from the curl man page:
2 Failed to initialize.
So far I've tried to pipe the output of man curl to grep like so:
Assuming $RETCODE=${?} after running a curl command...
lewis#hostname:~$ man curl | grep "${RETCODE}"
http://www.letters.com/file[a-z:2].txt
in the format "NAME1=VALUE1; NAME2=VALUE2".
out to be in text mode for win32 systems.
from outputting that and return error 22.
re-use the same IP address it already uses for the control connection. (Added in 7.14.2)
...
...
But this picks up a ton of other text featuring the number. Given that the exit code section is indented I have tried
lewis#hostname:~$ man curl | grep " ${RETCODE}"
2) On windows, if there is no _curlrc file in the home dir, it
2 Failed to initialize.
227-line.
21 FTP quote error. A quote command returned error from the server.
...
And as you can see, we're close. The text I'd like is there but it still returns incorrect results.
Note, for exit codes with two or more digits the white space to the right of the number in the man pages is reduced.

$ man curl | sed -n -e '/^E..X..I..T/,/^A..U..T..H/!d' -e '/ 2 /p'

Try this:
man curl | grep -E "^\s+${RETCODE}\s+"

Try:
man curl | egrep " {7}${RETCODE} +\S+"

Related

Base64 encoding from a website and terminal give two different results

I used following command on terminal
`echo admin:admin | base64`
It gives me following output
YWRtaW46YWRtaW4K
But when I used https://www.base64encode.org/ for the same string admin:admin it gives me following
YWRtaW46YWRtaW4=
Any reason for this?
The reason this behaviour is the new line added by the echo command. Normally the echo command add a new line at the end which leads to a different encoding. Therefore if you use it with echo -n admin:admin | base64 the difference won't occur.

Internal Variable PIPESTATUS

I am new to linux and bash scripting and i have query about this internal variable PIPESTATUS which is an array and stores the exit status of individual commands in pipe.
On command line:
$ find /home | /bin/pax -dwx ustar | /bin/gzip -c > myfile.tar.gz
$ echo ${PIPESTATUS[*]}
$ 0 0 0
working fine on command line but when I am putting this code in a bash script it is showing only one exit status. My default SHELL on command line is bash only.
Somebody please help me to understand why this behaviour is changing? And what should I do to get this work in script?
#!/bin/bash
cmdfile=/var/tmp/cmd$$
backfile=/var/tmp/backup$$
find_fun() {
find /home
}
cmd1="find_fun | /bin/pax -dwx ustar"
cmd2="/bin/gzip -c"
eval "$cmd1 | $cmd2 > $backfile.tar.gz " 2>/dev/null
echo -e " find ${PIPESTATUS[0]} \npax ${PIPESTATUS[1]} \ncompress ${PIPESTATUS[2]} > $cmdfile
The problem you are having with your script is that you aren't running the same code as you ran on the command line. You are running different code. Namely the script has the addition of eval. If you were to wrap your command line test in eval you would see that it fails in a similar manner.
The reason the eval version fails (only gives you one value in PIPESTATUS) is because you aren't executing a pipeline anymore. You are executing eval on a string that contains a pipeline. This is similar to executing /bin/bash -c 'some | pipe | line'. The thing actually being run by the current shell is a single command so it has a single exit code.
You have two choices here:
Get rid of eval (which you should do anyway as eval is generally something to avoid) and stop using a string for a command (see Bash FAQ 050 for more on why doing this is a bad idea.
Move the echo "${PIPESTATUS[#]}" into the eval and then capture (and split/parse) the resulting output. (This is clearly a worse solution in just about every way.)
Instead of ${PIPESTATUS[0]} use ${PIPESTATUS[#]}
As with any array in bash PIPESTATUS[0] contains the first command exit status. If you want to get all of them you have to use PIPESTATUS[#] which returns all the contents of the array.
I'm not sure why it worked for you when you tried it in the command line. I tested it and I didn't get the same result as you.

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.

Using -s command in bash script

I have a trivial error that I cant seem to get around. Im trying to return the various section numbers of lets say "man" since it resides in all the sections. I am using the -s command but am having problems. Every time I use it I keep getting "what manual page do you want". Any help?
In the case of getting the section number of a command, you want something like man -k "page_name" | awk -F'-' "/^page_name \(/ {print $1}", replacing any occurrence of page_name with whatever command you're needing.
This won't work for all systems necessarily as the format for the "man" output is "implementation-defined". In other words, the format on FreeBSD, OS X, various flavours of Linux, etc. may not be the same. For example, mine is:
page_name (1) - description
If you want the section number only, I'm sure there is something you can do such as saving the result of that line in a shell variable and use parameter expansion to remove the parentheses around the section number:
man -k "page_name" | awk -F'-' "/^page_name \(/ {print $1}" | while IFS= read sect ; do
sect="${sect##*[(]}"
sect="${sect%[)]*}"
printf '%s\n' "$sect"
done
To get the number of sections a command appears in, add | wc -l at the end on the same line as the done keyword. For the mount command, I have 3:
2
2freebsd
8
You've misinterpreted the nature of -s. From man man:
-S list, -s list, --sections=list
List is a colon- or comma-separated list of `order specific' manual sections to search. This option overrides the
$MANSECT environment variable. (The -s
spelling is for compatibility with System V.)
So when man sees man -s man it thinks you want to look for a page in section "man" (which most likely doesn't exist, since it is not a normal section), but you didn't say what page, so it asks:
What manual page do you want?
BTW, wrt "man is just the test case cuz i believe its in all the sections" -- nope, it is probably only in one, and AFAIK there isn't any word with a page in all sections. More than 2 or 3 would be very unusual.
The various standard sections are described in man man too.
The correct syntax requires an argument. Typically you're looking for either
man -s 1 man
to read the documentation for the man(1) command, or
man -s 7 man
to read about the man(7) macro package.
If you want a list of standard sections, the former contains that. You may have additional sections installed locally, though. A directory listing of /usr/local/share/man might reveal additional sections, for example.
(Incidentally, -s is not a "command" in this context, it's an option.)

Need help coloring/replacing arbitrary strings using Bash and sed

I'm using a bash script based on the technique used here: Get color output in bash to color the output of my builds and other scripts to make things easier to read. One of the steps in my build executes a "git pull" and the git server spits out a "welcome" string like this amidst a bunch of other output:
** WARNING: THIS IS A PRIVATE NETWORK. UNAUTHORIZED ACCESS IS PROHIBITED. **
Use of this system constitutes your consent to interception, monitoring,
and recording for official purposes of information related to such use,
including criminal investigations.
I'd like to color this specific message yellow or possibly delete it from the output while leaving the rest of the output alone. I've tried to replace a simple string like this:
WelcomeMessage="WARNING"
pathpat=".*"
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
git pull 2>&1 | sed -r -e "/$WelcomeMessage/ s%$pathpat%$ccyellow&$ccend%g"
The first line of the welcome string is colored yellow as expected but the rest of the lines are not. I'd really like to color the exact welcome string and only that string but for many reasons, this doesn't work:
WelcomeMessage="** WARNING: THIS IS A PRIVATE NETWORK. UNAUTHORIZED ACCESS IS PROHIBITED. **
Use of this system constitutes your consent to interception, monitoring,
and recording for official purposes of information related to such use,
including criminal investigations."
pathpat=".*"
ccred=$(echo -e "\033[0;31m")
ccyellow=$(echo -e "\033[0;33m")
ccend=$(echo -e "\033[0m")
git pull 2>&1 | sed -r -e "/$WelcomeMessage/ s%$pathpat%$ccyellow&$ccend%g"
This fails with the error: sed: -e expression #1, char 78: unterminated address regex
I've looked at a couple other questions and I was able to get the asterisks escaped (by preceding them with backslashes) but I'm baffled by the periods and multiple lines. I'd like to continue using sed to solve this problem since it integrates nicely with the colorizing solution.
Any help is appreciated. Thanks!
The following will colorize in yellow every line from the first instance of ** to the first instance of a period . that's not on the same line. This will match the entire warning message as written.
NORMAL=$(tput sgr0)
YELLOW=$(tput setaf 3)
git pull 2>&1 | sed "/\*\*/,/\./s/.*/$YELLOW&$NORMAL/"
Note: If you want to delete the message you can use this:
git pull 2>&1 | sed '/\*\*/,/\./d'

Resources