开发:Shell 学习之路

简单介绍

你能不能用shell判断一个文件中的数字是否有序啊?想想这不挺简单的吗,就开始动手写了,然后就有了这个版本。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#!bin/sh

filename=$1
before=-1;
flag=1;
for line in `cat data.txt`;
do
after=${line};
echo $line
if [ "$before">"$after" ];then
echo "FAILED";
flag=0;
break;
else
before=${line};
fi
done

if [ $flag = 1 ];then
echo "SUCCESS"
fi

哎呀,shell里不是有自带的sort命令吗,怎么不懂得试试那个sort呢。于是我就查阅了相关博客 * Linux下Sort命令的一些使用技巧 * LINUX SHELL脚本攻略笔记[速查]

返回值

原来shell脚本的返回值不是直接返回啊,而是通过 linux中shell变量$#,$@,$0,$1,$2的含义解释:

变量说明:

`$$` 
Shell本身的PID(ProcessID) 
`$!` 
Shell最后运行的后台Process的PID 
`$?` 
最后运行的命令的结束代码(返回值) 
`$-` 
使用Set命令设定的Flag一览 
`$*` 
所有参数列表。如"$*"用「"」括起来的情况、以`$1 $2 … $n`的形式输出所有参数。 
`$@` 
所有参数列表。如"`$@`"用「"」括起来的情况、以"`$1`" "`$2`" … "`$n`" 的形式输出所有参数。 
`$#` 
添加到Shell的参数个数 
`$0` 
Shell本身的文件名 
`$1~$n` 
添加到Shell的各参数值。`$1`是第1参数、`$2`是第2参数…。 

因此判断一个文件是否是有序的sort返回结果需要通过$?的值进行判断。可是sort是按照行来判断是否有序的,而不是判断所有的是否有序的。比如说datafile 中内容如下:

1
2
3
1 2 3 4 5 6 8 9
2 3 4 5 6 7 5 32
3 4 5 6 6 34 3

按照默认sort 情况下,上述文件是有序的。但是实际上总体来说,我们需要返回该文件为无序的,因此,sort的方案只好作罢。

数字比较

后来看看之前那个实现的逻辑,应该是没有什么大问题的呀。

数字的比较

-eq 相等(equal) -ne 不等(not equal) -gt 大于(greater than) -lt 小于(less than) -ge 大于等于 (greater than or equal) -le 小于等于 (less than or equal)

字符串的比较

[ $str1 = $str2 ] # 等于 [ $str1 != $str2 ] # 不等于 [ -z $str ] #空字符串返回true [ -n $str ]或者[ $str ] #非空字符串返回true

OMG, 原来shell里的>不是大于号啊,而是表示输入输出,下面就查找了一下关于linux标准文件描述符: | 文件描述符| 缩写| 描述| |----:|------:|------:| |0 | STDIN |标准输入 | |1 |STDOUT | 标准输出| |2 |STDERR | 标准错误|
标准输入和标准输出指的就是键盘和显示器。 当文件描述符(0,1,2)与重定向符号<组合之后,就可以重新定向输入,输出,及错误。 * command 2>file1 命令执行的错误信息保存到了file1文件中。显示屏只是显示正确的信息。 * command 1>file1 2>file2 命令执行后,没有显示。因为正确输出到file1,错误定向到file2 * command &>file1 命令执行后,输出和错误都定向到file1中 在shell脚本中,可以定义“错误”输出到STDERR指定的文件.需要在重定向符和文件描述符之间加一个and符&

经过这番折腾,终于在shell下将这个简单的问题搞定了!!!

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
#!bin/sh
function is_sorted()
{
before=-1;
flag=1;
for line in $(<$1); do
if [ $before -gt $line ];then
echo "Failed at $before, $line"
flag=0
break
fi
before=$line;
done

if [ $flag = 1 ];then
echo "SUCCESS"
fi
}

is_sorted $1

调用函数的方法为 is_sorted datafilename 或者调用bash脚本 bashfilename.sh datafilename

一个脚本

功能介绍

  • 支持简单模型,符合模型的解压
  • 支持目录下所有模型的解压
  • 解压模型按照模型名称创建目录

编写过程中一些问题总结

  1. models=(find . -name "*.model") 将找到的结果保存为一个数组需要加一个 (),否则是独立的多个元素;
  2. 善于利用linux提供的命令工具

例如通过basename的操作将文件的路径前缀(文件夹路径)去掉。强烈推荐 linux开发常用的文本处理命令

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
#!/bin/sh
# Decrypt the model
# create: 2019-05-22
function export_tar_model() {
tar_name=$1
target="${tar_name%.*}"
if [ -d ${target} ]; then rm -rf ${target}; fi
mkdir ${target}
tar -xf ${tar_fname} -C ${target}
cd ${target}
models=(`find . -name "*.model"`) # 将找到的结果保存为一个数组需要加 ()
for model in $models; do
base_m=`basename ${model}` # 通过basename的操作将文件的文件夹路径去掉
# echo $base_m
t="${base_m%.*}"
mkdir ${t}
tar -xf ${base_m} -C ${t} # 解压子模型
done
cd ..
}
function decrypt() {
input=$1
tar_fname="${input%.*}.tar"
target="${input%.*}"
model_tool decrypt $1 ${tar_fname}
export_tar_model ${tar_fname}
rm $tar_fname
}
function decrypt_models() {
cd $1
models=(`find . -name "*.model"`) # 将找到的结果保存为一个数组需要加 ()
for model in $models; do
decrypt $model
done
}
decrypt $1
# decrypt_models $1

crontab定时任务

这个功能在linux下定时执行一个任务,特别适合我这种需要每天查看日志,分析日志的人。比如现在我们的组项目中的dailybuild,被我写了一个脚本,每天将问题提取之后的内容分发的各位同事,非常方便。

使用注意

  • 执行时间要再三确认,往往配置crontab之后,3~5min之后才会生效
  • 需要用的语言解析器,例如python2.7, 要写绝对路径,绝对路径,绝对路径,这个比较保险。
  • 运行的输出最好重定向到文件,方便查看问题 /usr/bin/python2.7 /data/xxxxx.py > runtime.log 2>&1

LeetCode Shell Test

Word Frequency

Write a bash script to calculate the frequency of each word in a text file words.txt.

For simplicity sake, you may assume:

words.txt contains only lowercase characters and space ' ' characters. Each word must consist of lowercase characters only. Words are separated by one or more whitespace characters.

cat words.txt | tr -s ' ' '\n' | sort | uniq -c | sort -r | awk '{ print $2, $1 }'

  • tr -s: truncate the string with target string, but only remaining one instance (e.g. multiple whitespaces)

  • sort: To make the same string successive so that uniq could count the same string fully and correctly.

  • uniq -c: uniq is used to filter out the repeated lines which are successive, -c means counting

  • sort -r: -r means sorting in descending order

  • awk '{ print $2, $1 }': To format the output, see here.

  • Linux 中使用awk

  • awk_1line

  • shell基础知识