Chapter 7 Intermediate Shell Tool I

1.1 Sifting Through Files for a String

The grep command searches through files looking for the expression you supply:

[maxwell@MaxwellDBA test]$ grep printf *.c
grep: *.c: No such file or directory
[maxwell@MaxwellDBA test]$ grep bash *.sh
check_arg_count.sh:#!/usr/bin/env bash
checkfile.sh:#!/usr/bin/env bash
checkstr.sh:#!/usr/bin/env bash
check_unset_parms.sh:#!/usr/bin/env bash
chmod_all2.sh:#!/usr/bin/env bash
chmod_all.sh:#!/usr/bin/env bash
dbinit.sh:#!/usr/bin/env bash
donors.sh:#!/bin/bash
ext.sh:#!/bin/bash
fun_calc.sh:#!/usr/bin/env bash
func_choice1.sh:#!/bin/bash
func_choose.sh:#!/bin/bash
myscript.sh:#!/bin/bash
readability.sh:#!/bin/bash
rpncalc.sh:#!/usr/bin/env bash
select_dir.sh:#!/bin/bash
simpls.sh:#!/bin/bash
strvsnum.sh:#!/usr/bin/env bash
suffixer.sh:#!/usr/bin/env bash
suffixer.sh:# rename files that end in .bad to be .bash
suffixer.sh:    mv "${FN}" "${FN%bad}bash"
trackmatch.sh:#!/usr/bin/env bash
use_up_option.sh:#!/usr/bin/env bash
[maxwell@MaxwellDBA test]$ 
[maxwell@MaxwellDBA test]$ grep bash /home/maxwell/shelllearning/test/*.sh /home/maxwell/shelllearning/anotherdir/*.sh
/home/maxwell/shelllearning/test/check_arg_count.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/checkfile.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/checkstr.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/check_unset_parms.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/chmod_all2.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/chmod_all.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/dbinit.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/donors.sh:#!/bin/bash
/home/maxwell/shelllearning/test/ext.sh:#!/bin/bash
/home/maxwell/shelllearning/test/fun_calc.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/func_choice1.sh:#!/bin/bash
/home/maxwell/shelllearning/test/func_choose.sh:#!/bin/bash
/home/maxwell/shelllearning/test/myscript.sh:#!/bin/bash
/home/maxwell/shelllearning/test/readability.sh:#!/bin/bash
/home/maxwell/shelllearning/test/rpncalc.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/select_dir.sh:#!/bin/bash
/home/maxwell/shelllearning/test/simpls.sh:#!/bin/bash
/home/maxwell/shelllearning/test/strvsnum.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/suffixer.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/suffixer.sh:# rename files that end in .bad to be .bash
/home/maxwell/shelllearning/test/suffixer.sh:    mv "${FN}" "${FN%bad}bash"
/home/maxwell/shelllearning/test/trackmatch.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/test/use_up_option.sh:#!/usr/bin/env bash
/home/maxwell/shelllearning/anotherdir/func_choice1.sh:#!/bin/bash
/home/maxwell/shelllearning/anotherdir/func_choose.sh:#!/bin/bash
[maxwell@MaxwellDBA test]$ 

If you don't want to see the specific filenames,you may turn this off using the -h switch to grep:

[maxwell@MaxwellDBA test]$ grep -h bash *.sh 
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/usr/bin/env bash
#!/bin/bash
#!/bin/bash
#!/usr/bin/env bash
#!/bin/bash
#!/bin/bash
#!/bin/bash
#!/bin/bash
#!/usr/bin/env bash
#!/bin/bash
#!/bin/bash
#!/usr/bin/env bash
#!/usr/bin/env bash
# rename files that end in .bad to be .bash
    mv "${FN}" "${FN%bad}bash"
#!/usr/bin/env bash
#!/usr/bin/env bash

If you don't want to see the actual lines from the file, but only a count of the number of times the expression is found, then use the -c option.

[maxwell@MaxwellDBA test]$ grep -c bash *.sh 
check_arg_count.sh:1
checkfile.sh:1
checkstr.sh:1
check_unset_parms.sh:1
chmod_all2.sh:1
chmod_all.sh:1
dbinit.sh:1
donors.sh:1
ext.sh:1
fun_calc.sh:1
func_choice1.sh:1
func_choose_man1.sh:0
func_choose.sh:1
myscript.sh:1
quoted.sh:0
readability.sh:1
rpncalc.sh:1
select_dir.sh:1
simplest.sh:0
simpls.sh:1
strvsnum.sh:1
suffixer.sh:3
trackmatch.sh:1
tricky.sh:0
trythis.sh:0
use_up_option.sh:1
[maxwell@MaxwellDBA test]$ 

1.2 Getting Just the Filename from a Search

Use the -l option of grep to get just the filenames:

[maxwell@MaxwellDBA test]$ grep -l bash *.sh
check_arg_count.sh
checkfile.sh
checkstr.sh
check_unset_parms.sh
chmod_all2.sh
chmod_all.sh
dbinit.sh
donors.sh
ext.sh
fun_calc.sh
func_choice1.sh
func_choose.sh
myscript.sh
readability.sh
rpncalc.sh
select_dir.sh
simpls.sh
strvsnum.sh
suffixer.sh
trackmatch.sh
use_up_option.sh
[maxwell@MaxwellDBA test]$ 

1.3 Getting a Simple True/False from a Search

Use -q, the "quiet" option for grep. Or,for maximum portability,just throw the output away by redirecting it into /dev/null.Either way, your answer is in the bash return status variable $?

[maxwell@MaxwellDBA test]$ grep -q bash fun_calc.sh
[maxwell@MaxwellDBA test]$ if [ $? -eq 0 ] ; then echo yes ; else echo nope ; fi
yes
[maxwell@MaxwellDBA test]$ 

If we list multiple filenames after grep -q, then grep stops searching after the very first occurence of the search string being found.if you really need to read through all the files, then rather than use -q you can do this :

[maxwell@MaxwellDBA test]$ grep bash fun_calc.sh > /dev/null
[maxwell@MaxwellDBA test]$ if [ $? -eq 0 ] ; then echo yes ; else echo nope ; fi
yes
[maxwell@MaxwellDBA test]$ 

The redirecting to /dev/null sends the output to a special kind of device, a bit bucket, that just throws everything you give it away.

1.4 Searching for Text While Ignoring Case

Use the -i option on grep to ignore case:

[maxwell@MaxwellDBA test]$ grep -i bash *sh
check_arg_count.sh:#!/usr/bin/env bash
checkfile.sh:#!/usr/bin/env bash
checkstr.sh:#!/usr/bin/env bash
check_unset_parms.sh:#!/usr/bin/env bash
chmod_all2.sh:#!/usr/bin/env bash
chmod_all.sh:#!/usr/bin/env bash
dbinit.sh:#!/usr/bin/env bash
donors.sh:#!/bin/bash
ext.sh:#!/bin/bash
fun_calc.sh:#!/usr/bin/env bash
func_choice1.sh:#!/bin/bash
func_choose.sh:#!/bin/bash
myscript.sh:#!/bin/bash
readability.sh:#!/bin/bash
rpncalc.sh:#!/usr/bin/env bash
select_dir.sh:#!/bin/bash
simpls.sh:#!/bin/bash
strvsnum.sh:#!/usr/bin/env bash
suffixer.sh:#!/usr/bin/env bash
suffixer.sh:# rename files that end in .bad to be .bash
suffixer.sh:    mv "${FN}" "${FN%bad}bash"
trackmatch.sh:#!/usr/bin/env bash
trackmatch.sh:  echo Track ${BASH_REMATCH[2]} is ${BASH_REMATCH[3]}
trackmatch.sh:  mv "$CDTRACK" "Track${BASH_REMATCH[2]}"
use_up_option.sh:#!/usr/bin/env bash
[maxwell@MaxwellDBA test]$ 

A case-insensitive search finds messages written "BASH","bash","Bash",as well as ones like "BaSH" and "bAsH".This option is particularly useful for finding words anywhere that you might have mixed-case text, including words that might be capitalized at the beginning of a sentence or email addresses.

1.5 Doing a Search in a Pipeline

Just pipe your result into grep

If you also want to have grep search error messages that come from the previous command, be sure to redirect its error output into standard output before the pipe:

gcc bigbadcode.c 2>&1 | grep -i error 

This command attempts to compile some hypothetical, hairy piece of code. We redirect standard error into standard output ( 2>&1) before we proceed to pipe (|) the output into grep, where it will search case-insensitively (-i) looking for the string error.

1.6 Paring Down What the Search Finds

Pipe the results into grep -v with an expression that describes what you don’t want to see.

# you’re not sure if it’s always written as Dec, so to be sure to catch them all you type:

[maxwell@MaxwellDBA test]$ grep -i dec logfile
error on Jan 01: not a decimal number
error on Feb 13: base converted to Decimal
warning on Mar 22: using only decimal numbers
error on Dec 16 : the actual message you wanted
error on Jan 01: not a decimal number

# A quick and dirty solution in this case is to pipe the first result into a second grep and tell the second grep to ignore any instances of “decimal”:

[maxwell@MaxwellDBA test]$ grep -i dec logfile | grep -vi decimal
error on Dec 16 : the actual message you wanted
[maxwell@MaxwellDBA test]$ grep -i dec logfile | grep -vi decimal | grep -vi decimate
error on Dec 16 : the actual message you wanted

# a better solution would be to use a more powerful regular expression to match the December date. one that looked for "Dec" followed by a space and two digits:
[maxwell@MaxwellDBA test]$ grep 'Dec [0-9][0-9]' logfile
error on Dec 16 : the actual message you wanted
[maxwell@MaxwellDBA test]$ grep Dec\ [0-9\ ][0-9] logfile
error on Dec 16 : the actual message you wanted
[maxwell@MaxwellDBA test]$ 

1.8 Search for an SSN

[maxwell@MaxwellDBA test]$ grep '[0-9]\{3\}-\{0,1\}[0-9]\{2\}-\{0,1\}[0-9]\{4\}' datafile
grep: datafile: No such file or directory
[maxwell@MaxwellDBA test]$ 
[0-9]\{3\} -\{0,1\} [0-9]\{2\} -\{0,1\} [0-9]\{4\}

The first grouping says “any digit” then “exactly 3 times.” The next grouping says “a dash” then “0 or 1 time.” The third grouping says “any digit” then “exactly 2 times.” The next grouping says “a dash” then “0 or 1 time.” The last grouping says “any digit” then “exactly 4 times.”

1.9 Grepping Compressed Files.

zgrep is simply a grep that understands various compressed and uncompressed files (which types are understood varies from system to system).

zgrep 'search term' /var/log/messages*

zcat is simply a cat that understands various compressed and uncompressed files (which types are understood varies from system to system).

1.10 Keeping Some Output,Discarding the Rest

The following code prints the first word of every line of input:

The awk utility reads data from the filename supplied on the command line, or from standard input if no filename is given.

[maxwell@MaxwellDBA test]$ awk '{print $1}' myinput.file
zcat
(which
Words
supplied
[maxwell@MaxwellDBA test]$ awk '{print $1}' < myinput.file
zcat
(which
Words
supplied
[maxwell@MaxwellDBA test]$ 
[maxwell@MaxwellDBA test]$ cat myinput.file | awk '{print $1}'
zcat
(which
Words
supplied
[maxwell@MaxwellDBA test]$ cat myinput.file
zcat is simply a cat that understands various compressed and uncompressed files
(which types are understood varies from system to system).
Words are delineated by whitespace. The awk utility reads data from the filename
supplied on the command line, or from standard input if no filename is given. Therefore, you can redirect the input from a file, like this
[maxwell@MaxwellDBA test]$ 

1.11 Keeping Only a Portion of a Line of Output

Pipe ls into awk,and just pull out the fields that you need.
awk has a built-in variable called NF that holds the number of fields found on the current line, $NF always refers to the last field.

Just remember that you don’t use a $ to read the value of an awk variable (unlike bash variables). NF is a valid variable reference by itself. Adding a $ before it changes its meaning from “the number of fields on the current line” to “the last field on the current line.”

[maxwell@MaxwellDBA test]$ ls -l | awk '{print $1, $NF}'
total 156
-rw-rw-r-- amazing.data
-rw-rw-r-- another.file
-rw-rw-r-- a.out
-rwxr-x--- asdfwednnrw2rs2esff.txt
-rw-rw-r-- check_arg_count.sh
-rw-rw-r-- checkfile.sh
-rw-rw-r-- checkstr.sh
-rw-rw-r-- check_unset_parms.sh
-rw-rw-r-- chmod_all2.sh
-rw-rw-r-- chmod_all.sh
-rwxr-x--- cong.txt
-rw-rw-r-- dashes
[maxwell@MaxwellDBA test]$ 

1.12 Reversing the Words on Each Line

[maxwell@MaxwellDBA test]$ awk '{for (i=NF; i>0; i--) {printf "%s ", $i;} printf "\n" }'
sdjsf
sdjsf 
fsf
fsf 
ssfs
ssfs 
sfs
sfs 
sfs
sfs 
^C
[maxwell@MaxwellDBA test]$ awk '{                                                       
                               for (i=NF; i>0; i--) {
                                   printf "%s", $i;
                               }
                               printf "\n"
                           }'
sdafada
sdafada
ddsda
ddsda
fssdn
fssdn
^C
[maxwell@MaxwellDBA test]$ 

1.13 Summing a List of Numbers

Use awk both to isolate the field to be summed and to do the summing.

[maxwell@MaxwellDBA test]$ ls -l | awk '{sum += $5} END {print sum}'
9527
[maxwell@MaxwellDBA test]$ ls -l
total 156
-rw-rw-r-- 1 maxwell maxwell   0 Jul 26 10:20  amazing.data
-rw-rw-r-- 1 maxwell maxwell  65 Jul 21 21:10  another.file
-rw-rw-r-- 1 maxwell maxwell  10 Jul 21 15:39  a.out
-rwxr-x--- 1 maxwell maxwell  49 Jul 21 20:43  asdfwednnrw2rs2esff.txt
-rw-rw-r-- 1 maxwell maxwell 487 Jul 25 10:17  check_arg_count.sh
-rw-rw-r-- 1 maxwell maxwell 487 Jul 26 10:19  checkfile.sh
-rw-rw-r-- 1 maxwell maxwell 292 Jul 26 14:35  checkstr.sh
-rw-rw-r-- 1 maxwell maxwell 263 Jul 25 12:23  check_unset_parms.sh
-rw-rw-r-- 1 maxwell maxwell 199 Jul 25 09:36  chmod_all2.sh
-rw-rw-r-- 1 maxwell maxwell 160 Jul 25 07:55  chmod_all.sh
-rwxr-x--- 1 maxwell maxwell  19 Jul 21 15:40  cong.txt
-rw-rw-r-- 1 maxwell maxwell 399 Jul 26 20:23  dashes
-rw-rw-r-- 1 maxwell maxwell 185 Jul 26 20:36  dbinit.sh
-rw-rw-r-- 1 maxwell maxwell  15 Jul 21 15:40  def.conf
-rwxrwxr-x 1 maxwell maxwell 123 Jul 22 12:01  donors.sh
-rw-rw-r-- 1 maxwell maxwell 867 Jul 25 05:43  embedded_documenta

1.14 Counting String Values

Use awk's associative arrays for your counting.

[maxwell@MaxwellDBA test]$ ls -lR /usr/local | awk -f asar.awk
ls: cannot open directory '/usr/local/aegis/globalcfg/aegisdb': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/cache': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/quara_hex': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/quarantine': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/vulfilebackup': Permission denied
root owns 5306 files
[maxwell@MaxwellDBA test]$ cat asar.awk
#
# cookbook filename: asar.awk
#
NF > 7 {
        user[$3]++
     }
 END {
         for (i in user)
             {
                printf "%s owns %d files\n", i, user[i]
             }
     }

[maxwell@MaxwellDBA test]$ 

1.15 Showing Data As a Quick and Easy Histogram

Use the associate arrays of awk, as discussed in the previous recipe:

[maxwell@MaxwellDBA test]$ cat hist.awk
#
# cookbook filename: hist.awk
#
function max(arr, big)
{
   big = 0
   for (i in user)
   {
       if (user[i] > big) { big=user[i];}
   }
   return big
}

NF > 7 {
        user[$3]++
     }
 END {
        # for scaling
        maxm = max(user);
        for (i in user)
        {
          #printf "%s owns %d files\n",i,user[i]
          scaled = 60 * user[i] / maxm ;
          printf "%-10.10s [%8d]:", i, user[i]
          for (i=0; i<scaled; i++) {
              printf "#";
          }
          printf "\n"
        }
     }
[maxwell@MaxwellDBA test]$ ls -lR /usr/local | awk -f hist.awk
ls: cannot open directory '/usr/local/aegis/globalcfg/aegisdb': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/cache': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/quara_hex': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/quarantine': Permission denied
ls: cannot open directory '/usr/local/aegis/globalcfg/vulfilebackup': Permission denied
root       [    5306]:############################################################
[maxwell@MaxwellDBA test]$ 

1.16 Showing a Paragraph of Text After a Found Phrase

[maxwell@MaxwellDBA test]$ awk -f para.awk < myinput.file
[maxwell@MaxwellDBA test]$ cat para.awk
/keyphrase/ { flag=1 }
{ if (flag == 1) { print $0 }}
/^$/ { flag=0 }
[maxwell@MaxwellDBA test]$ 
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值