Learn Shell basic programming efficiently in two days (praise)

Posted by blr32 on Wed, 05 Jan 2022 17:24:22 +0100

preface

Try not to use all the questions. The commands tail, cat, grep and awk are directly executed to get the results. They are all programmed with bash shell statements, so the program is the most efficient

The following is my method of learning Shell for reference

1. Take half a day to see the basic usage: Shell tutorial - rookie tutorial
Note: if you find it boring to watch it directly, you can spend half a day brushing the first five simple questions of Niuke, look at the writing methods of the top few, get started a little, and then watch the rookie tutorial

2. Then take the Niuke Shell title It takes one day to finish the brush, but it won't. look at what others have written in the ranking. Try to follow their own ideas and complete it by yourself. Be sure to think and knock by yourself. Don't copy other people's operation. You can read other people's ideas and write by yourself, but don't look and write. It will take about two days in total. There will be no problem in the development of basic points of shell programming. You can learn faster and more deeply by doing more

If you think and complete 20 questions by yourself, there will be no problem with shell grammar and basic programming. Anyway, I feel so. I concentrate on brushing them in time

subject

20 channels

1. Count file lines

subject

describe
 Write one bash Script to output a text file nowcoder.txt Number of rows in
...

code

while read val # Read line by line, val is each line
do
# Every line read is + 1, that is, self increment
 ((line++))
done < ./nowcoder.txt # Redirect to the file every time you finish, continue reading, < indicates redirection
echo $line

2. Print the last 5 lines of the file

The code is directly on the back

#!/bin/bash
line=0
while read val
do
    line=$((line+1))
done < nowcoder.txt
 
line=$((line-5))
cnt=0
while read val
do
    if (($cnt >= $line )) # It is equivalent to not inputting in front of line, but inputting in the back of line
    then
        echo $val
    fi
    cnt=$((cnt+1))
done < nowcoder.txt

3. Multiple of output 7

for i in {0..500}
do
    if (( i % 7 == 0))
    then
        echo $i
    fi
done

4. Output line 5

#!bin/bash
num=1
while read line
do
    if ((num == 5))
    then
        echo $line
    fi
    ((num++))
done < nowcoder.txt

5. Print line number of blank line

#!/bin/bash
num=1
while read line
do
     if [ -z $line ]
     then
        echo $num
     fi
    ((num++))
done < nowcoder.txt

6. Remove blank lines

#!/bin/bash
while read line
do
    if [ -z $line ]
    then
        continue
    else
        echo $line
    fi
done < nowcoder.txt

7. Print words with letters less than 8

# Idea 1: first divide and store in the array, and then count them separately
# Idea 2: traverse the string, num=0, judge when you encounter a space, and see if it can be output
#!/bin/bash
read line < nowcoder.txt # Read nowcoder Txt line
for n in $line
do
    if [ "${#n}" -lt 8 ]
    then
        echo ${n}
    fi
done

8. Count the sum of the memory occupied by all processes

# Read each row, then get the second column value and add it
sum=0
while read line
do
    arr=($line)
    ((sum+=arr[5]))
done < nowcoder.txt
echo $sum

9. Count the number of occurrences of each word

The number of typical questions, de duplication and statistics are the same

# Problem solving steps:
# 1. Read line by line. The words of each line are stored in the map, which is equivalent to an initialization process
# 2. Use an array to store the number of occurrences of words after duplication
# 3. Bubble sorting
# 4. Compare the number of times after sorting with the value in the map, and output them in turn when they are equal. This is the sorted number

declare -A map

while read line
do
    arr=$line
    for i in ${arr[@]}
    do
        if [ -z ${map[$i]} ]
        then
            map[$i]=1
        else
            ((map[$i]++))
        fi
    done
 done < nowcoder.txt
 
 mm=()
 
for value in ${map[@]}
do
    mm[${#mm[@]}]=${value}
done

len=${#mm[@]}
for ((i=0;i<len;i++))
do
    for ((j=i+1;j<len;j++))
    do
        if [ ${mm[$i]} -gt ${mm[$j]} ]
        then
            tmp=${mm[$i]}
            mm[$i]=${mm[$j]}
            mm[$j]=$tmp
         fi
     done
 done
 
for ((k=0;k<len;k++))
do
    for key in ${!map[@]}
    do
        if [ ${map[$key]} -eq ${mm[$k]} ]
        then
            echo $key ${map[$key]}
        fi
    done
done

10. Is there any repetition in the second column

 # Problem solving steps
# 1. Construct a map, and the key value is the number of occurrences of the element in column 2
# 2. Put the number of occurrences of elements in the map into the array
# 3. Sort array
# 4. Output in sort order
declare -A map
# Step 1: construct map
while read -a line
do
    key=${line[1]}
    if [ -z ${map[${key}]} ]
    then
        map[${key}]=1
    else
        ((map[${key}]++))
        # echo $key ${map[${key}]}
    fi
done < nowcoder.txt
# Step 2: put the number of repeated elements into the array
arr=()
for key in ${!map[@]}
do
    if [ ${map[$key]} -gt 1 ]
    then
        echo ${map[$key]} $key
        arr[${#arr[@]}]=${map[$key]}
    fi
done
# Step 3: sort the arr array (number of occurrences)
len=${#arr{@}}
for (( i=0;i<len;i++ ))
do
    for (( j=$[$i+1];j<len;j++ ))
    do
        if [ ${arr[$i]} -gt ${arr[$j]} ]
        then
            # exchange
            tmp=${arr[$i]}
            arr[$i]=${arr[$j]}
            arr[$j]=$tmp
        fi
    done
done
#Step 4: output
for (( k=0;k<len;k++ ))
do
    for key in ${!map[@]}
    do
        if [ ${map[${key}]} -eq ${arr[$k]} ]
        then
            echo ${map[$key]} ${key}
        fi
    done
done

11. Transpose the contents of the file

# Read each row, get the number of trips and columns, and then traverse. Note that the shell has no two-dimensional array, but only one-dimensional array
# Step 1: read each row and put it into the array
arr=()
while read line
do
    arr[${#arr[@]}]=$line
done < nowcoder.txt
# Step 2: transpose output, that is, row column exchange traversal output
rows=${#arr[@]}
m=(${arr[0]})
columns=${#m[@]}
for (( i=0;i<$columns;i++ ))
do
    for (( j=0;j<$rows;j++ ))
    do
        tmp=(${arr[$j]})
        echo "${tmp[$i]} "
    done
done

12. Print the number of digits in each line

# String interception, regular expression
line_num=0 # Line number
sum=0 # Total number of figures
while read line
do
    count=0 # Record the number of digits in each line
    ((line_num++))
    for (( i=0;i<${#line};i++ ))
    do
        if [[ ${line:$i:1} =~ [1-5] ]]
        then
            ((count++))
        fi
    done
    ((sum+=count))
    echo "line${line_num} number:${count}"
done < nowcoder.txt
echo "sum is ${sum}"

13. Remove all sentences containing this

# Read each row and generate an array for each row to see whether it contains this. If yes, continue. Otherwise, output
while read line
do
    flag=0
    for i in $line
    do
        if [ $i == "this" ] # Note the difference between = = and - eq, = = compares strings, and - eq compares corresponding values
        then
            flag=1
            break
        fi
    done
    if [ $flag -eq 0 ]
    then
        echo $line
    fi
done < nowcoder.txt

14. Average

read len # Input length
loop_time=$len
sum=0
while (($loop_time > 0))
do
    read ele
    ((sum+=ele))
    ((loop_time--))
done
echo "scale=3;$sum/$len" | bc # The bc tool displays decimals

15. Remove unnecessary words

# Read input
while read line
do
    len=${#line}
    flag=1
    # Determine each character of the string
    for (( i=0;i<len;i++ ))
    do
        if [[ ${line:$i:1} == "B" || ${line:$i:1} == "b" ]]
        then
            flag=0
            break
        fi
    done
    if [ $flag -eq 1 ]
    then
        echo $line
    fi
done

16. Judge whether the input is an IP address

# It is composed of four digits, and the range of digits is 0 ~ 255
# How does Shell do separation? Press. Separated, returned to array, ${parameter//pattern/string}
while read line
do
    arr=(${line//./ })
    len=${#arr[@]}
    if [[ $len != 4 ]]
    then
        echo "error"
        continue
    fi
    flag=1
    for ele in ${arr[@]}
    do
        if [ $ele -ge 0 -a $ele -le 255 ]
        then
            continue
        else
            flag=0
            break
        fi
    done
    if [ $flag -eq 1 ]
    then
        echo "yes"
    else
        echo "no"
    fi
done < nowcoder.txt

17. Output the fields in reverse order to each line of the file

awk here will be faster and easier to understand. I use shell statements to write it myself. It's not easy to write

# NF indicates how many words are in a line, - F ":" indicates separated by:
awk -F ":" '{ for(i=NF;i>=1;i--)
                    if (i != 1){
                    {printf $i ":"}
                    } else {
                    {print $i}
                    }
        }' nowcoder.txt

18. Count and sort domain names

# This is similar to string repetition times and sorting
declare -A map
while read line
do
    tmp=(${line//\//}) # backslash escape
    name=${map[${tmp[1]}]}
    # echo $name
    if [ -z $name ]
    then
        map[${tmp[1]}]=1
    else
        ((map[${tmp[1]}]++))
    fi
done < nowcoder.txt
# Construct array
arr=()
for key in ${!map[@]}
do
    arr[${#arr[@]}]=${map[$key]}
done
len=${#arr[@]}
# Bubble is used to sort the array (descending)
for (( i=0;i<len;i++ ))
do
    for (( j=i+1;j<len;j++ ))
    do
        if [ ${arr[$i]} -lt ${arr[$j]} ]
        then
            tmp=${arr[$i]}
            arr[$i]=${arr[$j]}
            arr[$j]=$tmp
        fi
    done
done
# Output in array sort order
for (( k=0;k<len;k++ ))
do
    for key in ${!map[@]}
    do
        if [ ${map[${key}]} -eq ${arr[$k]} ]
        then
            echo ${map[$key]} ${key}
        fi
    done
done

19. Print isosceles triangles

I remember learning C language at the beginning. This is the textbook exercise

for (( i=1;i<=5;i++ ))
do
    # Print spaces
    for (( j=5-i;j>=1;j-- ))
    do
        printf " "
    done
    # Print stars
    for (( k=1;k<=i;k++ ))
    do
        printf "* "
    done
    printf "\n"
done

20. Print a line with only one number

while read line
do
    count=0
    for (( i=0;i<${#line};i++ ))
    do
        if [[ ${line:$i:1} =~ [0-9] ]]
        then
            ((count++))
        fi
    done
    if [ $count -eq 1 ]
    then
        echo $line
    fi
done < nowcoder.txt

Topics: Linux bash