bash


баш - это репозитарий скриптов, с историей и сорс-контролем

Ctrl-R

    w3m -dump google.com

    cat /proc/sys/kernel/random/entropy_avail
    
    there, that should tell you how many bits of entropy you've got
    It should be at least 2000


for x in a,b c,d e,f ; do
    KEY=${x%,*};                   # remove , and all after that
    VAL=${x#*,}                    # remove , andd all before that
    echo $KEY" " - " "$VAL
done    
  

  while read x; \
     do echo $x |socat -t 0.001 - udp-connect:127.0.0.1:33377 ; \
  done <inputfile >outputfile
  

$> tabs 2


comments start with #

variables can be nums, strings, arrays and assoc arrays:

  $> a="one two three"
  $> echo $a
   one two three
  $> echo ${a[1]}
   two

  $> read -a a <<< "one two three"
  $> echo ${a[2]}
  three
  $> read -a a <<< 'one two three'
  $> echo ${a[2]}
  three

  
  $> declare -A aa
  $> aa[hello]=world
  $> aa[ab]=cd

array iteration:

  ##    declare an array variable
  declare -a arr=("element1" "element2" "element3")

     ##  also works for multi-line array declaration

     # declare -a arr=("element1"
     #                 "element2" "element3"
     #                 "element4"
     #               )

  
  ##    loop through the above array
  for i in "${arr[@]}"
  do
     echo "$i"
  done


  for x in a b c d e f ; do
         echo "$x"
  done


  listOfNames="RA
  RB
  R C
  RD"

  for y in "$listOfNames"   
  do
    echo "$y"  
  done



  declare -A continent

  continent[Vietnam]=Asia
  continent[France]=Europe
  continent[Argentina]=America

  for item in "${!continent[@]}" ;
    do
      printf "$item is in ${continent[$item]} \n"
    done

  

   List="Item 1,Item 2,Item 3"
  
   Backup_of_internal_field_separator=$IFS
   IFS=,
  
   for item in $List ;
     do
       echo "$item"
     done

   IFS=$Backup_of_internal_field_separator


    arr=(foo bar baz)

    for i in ${!arr[@]}
    do
        echo $i "${arr[i]}"
    done




  declare -A array
  array[foo]=bar
  array[bar]=foo

  # the keys are accessed using an exclamation point: ${!array[@]}
  # the values are accessed using ${array[@]}

  for i in "${!array[@]}"
  do
    echo "key  : $i"
    echo "value: ${array[$i]}"
  done

  

"-A" declares aa to be an associative array. assignments are then made by putting the "key" inside the square brackets. you can also assign multiple items at once:

  declare -A aa
  aa=( [hello]=world [ab]=cd )
  # this is now if assign all keys to an array: kk=("${!aa[@]}")
  
  # retrieving vals:

  if [[ ${aa[hello]} == world ]]; then
     echo equal
  fi


  declare -A aa
  aa[hello]=world
  aa[ab]=cd




  for x in a,b c,d e,f ; do
      KEY=${x%,*}; VAL=${x#*,}
      echo $KEY" " - " "$VAL
  done



math in bash

foget abt arithmetics beyond "bc" - only inc dec + and - ops are "reliable without any magic"

$> x=12      
$> echo $x
12
$> echo $((++x))
13
$> echo $((x++))
13
$> echo $x
14
$> echo $((--x))
13
$> echo $((x--))
13
$> echo $x
12

$> let x=5
$> let y=$x+1
$> echo $x
5
$> echo $y
6


integer comparisons

-eq
equal to
if [ $a -eq $b ]

-ne
not equal to
if [ $a -ne $b ]

-gt
greater than
if [ $a -gt $b ]

-ge
greater than or equal to
if [ $a -ge $b ]

-lt
less than
if [ $a -lt $b ]

-le
less than or equal to
if [ $a -le $b ]

<
less than (within double parentheses)
(($a < $b))

<=
less than or equal to (within double parentheses)
(($a <= $b))

>
greater than (within double parentheses)
(($a > $b))

>=
greater than or equal to (within double parentheses)
(($a >= $b))

=
equal to
if [ $a = $b ]

!=
not equal to
if [ $a != $b ]

<
less than, in ASCII alphabetical order
if [[ $a < $b ]]
if [ $a \< $b ]
note that the "<" needs to be escaped within a [ ] construct.

>
greater than, in ASCII alphabetical order
if [[ $a > $b ]]
if [ $a \> $b ]
note that the ">" needs to be escaped within a [ ] construct


compound comparison

-a
logical and
exp1 -a exp2 returns true if both exp1 and exp2 are true

-o
logical or
exp1 -o exp2 returns true if either exp1 or exp2 is true

these are similar to the Bash comparison operators && and ||, used within double brackets
[[ condition1 && condition2 ]]
[[ condition1 || condition2 ]]


loops

#!/bin/bash

for x #in $1 $2
do
  echo `expr $x + 2`;
  echo `expr $x - 2`;
done

for a in `seq 10`
  do
    echo -n "$a "
  done

for a in {1..10}
  do
    echo -n "$a "
  done

read var0
limit=20
while [ "$var0" -lt "$limit" ]
    do
      echo -n "$var0"
      var0=$((++var0))        # var0=$(($var0 + 1))    also works
                              # let "var0 += 1"        also works
      echo
    done


end_cond=10
until [ "$var1" = "$end_cond" ]
do
  echo "Input variable # "
  echo "($end_cond to exit)"
  read var
  echo "variable # = $var"
  echo
done

exit 0

the break command may optionally take a parameter. a plain break terminates only the innermost loop in which it is embedded, but a break N breaks out of N levels of loop

the continue command, similar to break, optionally takes a parameter. a plain continue cuts short the current iteration within its loop and begins the next. a continue N terminates all remaining iterations at its loop level and continues with the next iteration at the loop, N levels above


branches


#!/bin/bash

select x in one two three
do
  case $x in
    one  ) echo $1; break;;
    two  ) read y; echo `expr $1 + $y`;;
    three) exit 0;;
  esac
done

functions

#!/bin/bash

func1 ()  {
  if [ $1 -gt $2 ]
    then echo `expr $1 - $2`;
    else echo `expr $2 + $1`;
  fi
}

func2 () {
  case $1 in
      1) echo `expr $2 + $3`;;
      2) echo `expr $2 + $3`;;
      *) echo "mistake";;
  esac
}

func1 5 7
func2 1 4 6

exit 0

the function must be defined before usage

useful command : shift n
delete first n params

example:

#!/run/current-system/sw/bin/bash

foo () { while [ -n "$5" ] ; do marr+=("$1 $2 $3 $4 $5") ; shift 5 ; done }

file=/home/user/puper/kvs/collect/ress.tch

./decode.sh $1 |while read y
do
  read harr <<< $( tchmgr get $file "$y" 2>/dev/null )
  foo $( echo $harr | tr ',' ' ' )
  printf "%s\n" "${marr[@]}" | tr ' ' ',' | cat >$$
  ans1=$( ./boomboom.sh "$y" )
  ans2=$( ./statboom.sh $$ 35 20 )
  printf "%-7s  %s %s\n" "${y:0:7}" "$ans1" "$ans2"
  rm $$
done

read a file line-by-line


  $ while read -r x;
    do
         # do something with $x
    done < file

  $ cat file | while read -r x;
    do
         # do something with $x
    done

redirect

command >file is the same as command 1>file

the number 1 stands for stdout, which is the file descriptor number for standard output

operator &> redirects both output streams - stdout and stderr - from command to file

you can redirect each stream one after another: command >file 2>&1

NB : command >file 2>&1 is not the same as command 2>&1 >file the order of redirects matters. the last command redirects only the standard output to the file,the stderr will still print to the terminal

 
     # - from file
     awk -e '{print $2;}' <filename

     # - from stdin
     awk -e '{print $2; }' <<MARK
     ...
     ...
     MARK

     # - from string
     awk -e '{print $2; }' <<<"my string as input"
once you read the file descriptor it is been exhausted and you need to close it and open it again to use it
   exec 4<filename
   while read x; do echo $x; done <&4
   4>&-

   exec 4>filename
   echo "foo" >&4
   exec 4>&-

   (command1; command2) >filename


   #redirect both output and error to /dev/null
   $> command > /dev/null 2>&1

   #redirect both standard output and standard error to a file
   $> command &>file

   $> find ./ -name "*.htm" > list.lst
   $> exec 4<list.lst
   $> while read x; do mv $x ${x/%htm/html}; done <&4

replacements in variables

  #from 7, eight chars:
  for i in *; do mv "$i" "${i:7:8}"; done

  #from 40, to the end:
  for i in *; do mv "$i" "${i:40}"; done

  mv ${x} ${x/#pattern/subs}    # from the begining of x
  mv ${x} ${x/%pattern/subs}    # from the end of x
  mv ${x} ${x//pattern/subs}    # replace elsewhere in x

#remove all spacebars:
  for x in stock*.html; do mv "${x}" "${x// /}"; done

#replace all spacebars for undescore:
  for x in *.html; do mv "${x}" "${x// /_}"; done

btw:
  for i in $(seq 1 200); do echo $i; done;


things

      cat      - output the contents of a file
      tac      - output the contents of files in reverse order

      printf   - formatted output
      
      tee   <param> file [file2, file3, ...] — route a input' contents to multiple outputs

      tr       - translate one set of characters to another

      cut      - output parts of each string
      paste    - clue several files together

      touch    - update the timestamp of a file or directory. create new if nessesary

   ls | tee log.txt
выведет список файлов текущего каталога на консоль и одновременно сохранит вывод в файл log.txt
если добавить к команде tee параметр -a, то информация будет дозаписываться в файл(ы). без этого параметра файлы будут перезаписаны