• 主页
  • 系列总集
  • OpenCV
  • CMake
  • iOS
  • Java
  • 前端
所有文章 关于我

  • 主页
  • 系列总集
  • OpenCV
  • CMake
  • iOS
  • Java
  • 前端

Shell三连(七):STDIN重定向执行字符串

2018-12-07

Sh 的 -c 参数

可以把一串字符串当作命令来执行, 以下结果是一样的

1
2
echo "Hello"
sh -c "echo \"Hello\""

sudo 获取多命令权限

如果我想通过重定向给一个没有权限的文件添加内容,使用直接写法会因为 给了echo权限,而没给重定向权限 失败

1
2
3
4
5
//Failure
sudo echo "Hello" >> /no_permission_file
//Success
sudo sh -c "echo \"Hello\"" >> /no_permission_file

Docker执行RUN CMD EXECUTE

Docker官方文档中有特意的提示,需要在Dockerfile里使用该方法触发RUN 和 CMD

1
2
Note: Unlike the shell form, the exec form does not invoke a command shell. ..... RUN [ "echo", "$HOME" ] ..... for example: RUN [ "sh", "-c", "echo $HOME" ].

或者在Host主机执行一些复杂的命令

1
2
docker exec -i $DOCKER_NAME sh -c "mysqldump -uroot -proot -P 3306 --default-character-set=utf8mb4 $DATABASE_NAME> $BACKUP_PATH"

  • Shell
  • Tips

展开全文 >>

Shell三连(六):如何读懂shell说明书man

2018-12-06

查找命令和说明

根据Linux基本知识

目的 操作
查找 输入任何字母,双击Tab,即可联想到相关命令
说明 输入man command,command代指任意命令

读懂说明

我们以 find 方法为例解释说明, 执行 man find

1
2
3
4
5
6
7
8
9
10
11
12
13
FIND(1)                   BSD General Commands Manual                  FIND(1)

NAME (这里是对该命令的简介)
find -- walk a file hierarchy

SYNOPSIS (这里是语法说明)
find [-H | -L | -P] [-EXdsx] [-f path] path ... [expression]
find [-H | -L | -P] [-EXdsx] -f path [path ...] [expression]

DESCRIPTION (这里是是详细说明)
The find utility recursively descends the directory tree for each path listed, evaluating an expression (composed of the
``primaries'' and ``operands'' listed below) in terms of each file in the tree.

这里主要是看 SYNOPSIS 的语法说明

符号 代表 说明
无修饰 find、path 必须输入,不可少
中括号 [-EXdsx]、[-f paht] 可选,可以不输入
省略号 … 可多个

也就是说 SYNOPSIS 中描述的两种命令要遵循以下几点

  1. find都是不可少的
  2. path 和 -f path 至少要存在一个
  3. 其他的都是可选的

细节就需要看详细说明 DESCRIPTION 之后的东西了

搜索关键字和退出

man 指令的是使用的类似 vim 命令模式,输入 q 可以直接退出

如果要搜索可以输入 /string 来搜索,使用n 或者 shift+n 来跳转下一个或者上一个关键词

  • Shell
  • Tips

展开全文 >>

Shell三连(五):递归遍历目录处理文件

2018-12-05

递归目录、处理文件

递归一个目录我们可以使用 find 命令得到每一行

并且将输出重定向到while方法

在while的条件判断中使用 read line 来处理每一行

read获取到 $line 变量,当无法读取到line则条件失败结束while循环

1
2
3
4
5
6
7
8
index=0
find . -name *.jpg | while read line;
do
index=$((index+1))
target="image$(printf "%03d" $index).jpg"
mv "$line" "./$fresh"
done

数字运算

根据我们示例代码,我们需要做个递增的index

根据StackOverfow的回答在shell中存在一个概念 Arithmetic Expansion 算术扩展, 可以使用如下表达

1
2
3
4
5
6
Use arithmetic expansion: $((EXPR))
num=$((num1 + num2))
num=$(($num1 + $num2)) # also works
num=$((num1 + 2 + 3)) # ...
num=$[num1+num2]

  • Shell
  • Tips

展开全文 >>

Shell三连(四):条件命令和管线Pipe命令

2018-12-04

多重命令执行

根据Linux教材里面提到了两种多重命令执行方式

条件命令 && ||

简单的与或逻辑,如果使用 && 就是前一个执行成功才执行后一个,而或逻辑 || 则前一个失败执行下一个

其基于逻辑命令的返回值是否等于0, 0为正常执行完毕

1
2
cd ~/Desktop && echo "first cmd return 0, this is second cmd" 
cd ~/Desktop2 || echo "first cmd return not 0, this is second cmd"

管线命令 Pipe

根据文章标准输入输出重定向可以把之前命令的标准输出(stdin)作为之后命令的输入(stdout)

以我们常见的grep举例

1
2
3
4
5
6
7
8
9
10
11

# 单独执行grep,会进入输入模式,如果换行前存在test,则会再次输出
grep "test"

# 单独执行 ls ,会列出当前目录的文件夹和文件
ls

# 管线操作
# 将ls的输出作为grep的输出,来过滤文件名
ls . | grep "test"

  • Shell
  • Tips

展开全文 >>

Shell三连(三):文件的读写和重定向

2018-12-03

文件读写

shell里最重要对一个概念就是流,所谓流就是 byte stream

面向流只有 输入 和 输出 默认的 输入是 stdin,输出是 stdout、stderr

输入和输出可以被重定向来管理字节流,从而达到文件读写的目的

文件操作 重定向逻辑
文件写 重定向输出stdout至文件
文件读 重定向文件至输入stdin

根据网络教程文件的重定向已经对基本知识介绍的很清楚,本文仅仅针对读写进行举例

文件写

1
2
3
4
5
6
7
8
9
echo "line1" > file.txt
cat file.txt //新建并写入一行字符串

echo "line2" >> file.txt
cat file.txt //追加一行字符串

echo "line3" > file.txt
cat file.txt //写入一行字符串并且替换原内容

文件读

文件读取到运行时的变量并不牵扯到重定向的逻辑, 直接使用 cat 获取文件内容并且赋值给变量即可

1
2
var1=$(cat file.txt)
echo "read var1 from file.txt : \n$var1"

如果非要使用 stdin 重定向,则可以使用以下代码,代表将 file.txt 作为输入并且dollar符号执行,结果赋值给var2

1
2
var2=$(<file.txt)
echo "read var2 from file.txt : \n$var2"

输入重定向是什么

对网络教程的补充

输出重定向很好理解,所有terminal的输出都会作为 byte stream保存到某个文件

而如何理解输入重定向,以下是对网络教程的补充

1
2
3
4
5
6
7
echo "line1" > file.txt
echo "line2" >> file.txt

wc -l file.txt // 输出 2 file.txt

wc -l < file.txt // 输出 2

其中 2 代表 2行, 为何第一个带有文件名,第二个不带文件名,我们通过 man wc 来分析,文档显示以下原文

1
2
3
4
5
6
7
8
9
//用于统计 词、行、字符、和比特数
wc -- word, line, character, and byte count

//-l 参数代表统计行数
-l The number of lines in each input file

//补充说明,如果没有文件输入,则从stdin读取,并且不显示文件名
If no files are specified, the standard input is used and no file name is displayed.
The prompt will accept input until receiving EOF, or [^D] in most environments.

其中 EOF(代表End of File),文件自然自带EOF,如果是 Here Document 通常是 Ctrl+D 用于输入一个EOF

可见仅仅输出 2 的shell命令执行了以下操作

  1. wc -l 不带文件名,触发从stdin读取
  2. < file.txt 将 file重定向到 stdin 作为输入
  3. file.txt 自带 EOF 输出行数且不带文件名

我们可以使用 Here Document 来模拟这个过程

1
2
3
4
wc -l
//输入line1 换行
//输入ling2 换行
//操作 Ctrl+D

为什么echo不能响应输入重定向

对于输入重定向,一般刚刚学会都会想使用echo 来输出文件重定向来的内容,但是执行完毕却没有输出类似的问题

1
echo < file.txt

原因在于 file.txt 的内容被重定向到了 stdin,但是echo指令并不会从 stdin 读取任何内容,所以无法输出文件的内容

所以说一个指令是否能否使用输入重定向,决定于它是否从stdin读取内容

一些教程中需要高亮的基础知识

文件描述符

一般情况下,每个 Unix/Linux 命令运行时都会打开三个文件:

  • 标准输入文件(stdin):stdin的文件描述符为0,Unix程序默认从stdin读取数据。
  • 标准输出文件(stdout):stdout 的文件描述符为1,Unix程序默认向stdout输出数据。
  • 标准错误文件(stderr):stderr的文件描述符为2,Unix程序会向stderr流中写入错误信息。

所以说如果使用了数字代替字符串,代表三个标准文件,例如将错误追加输出到file

1
command 2 >> file.txt

Here Document

Here Document 是 Shell 中的一种特殊的重定向方式,用来将输入重定向到一个交互式 Shell 脚本或程序

个人的理解,是用stdin 模拟一个基于运行时的文件,所以叫 Here Document

1
2
3
command << delimiter
document
delimiter

一般来讲 delimiter 使用 EOF

1
2
3
4
5
cat << EOF
line1
line2
line3
EOF

值得注意的两点

  1. 结尾的delimiter 一定要顶格写,前面不能有任何字符,后面也不能有任何字符,包括空格和 tab 缩进
  2. 开始的delimiter前后的空格会被忽略掉

>& 和 &>

这里的&没有固定的意思

放在>后面的&,表示重定向的目标不是一个文件,而是一个文件描述符,

换言之 2>1 代表将stderr重定向到当前路径下文件名为1的regular file中

而2>&1代表将stderr重定向到文件描述符为1的文件

1
2
$ command > file 2>&1
$ command >> file 2>&1

顺序问题

1
2
3
find /etc -name .bashrc > list 2>&1
# 我想问为什么不能调下顺序,比如这样
find /etc -name .bashrc 2>&1 > list
  1. 先将要输出到stdout的内容重定向到文件,此时文件list就是这个程序的stdout,再将stderr重定向到stdout,也就是文件list
  2. 先将要输出到stderr的内容重定向到stdout,此时会产生一个stdout的拷贝,作为程序的stderr,而程序原本要输出到stdout的内容,依然是对接在stdout原身上的,因此第二步重定向stdout,对stdout的拷贝不产生任何影响
  • Shell
  • Tips

展开全文 >>

Shell三连(二):如何使用正则获取变量

2018-12-02

心路历程

在shell的正则表达式里常用的有

  1. sed(stream editor)
  2. grep(file pattern searcher)
  3. BASH_REMATCH(Bash3.x自带表达式 =~ )

值得注意的是以上三种都不支持非贪婪模式(non-greedy)的匹配,因为无法对一行字符串进行多次匹配,参考regex in bash expression

Example

我们假设摘取以下字符串里的key值 some_important_string

1
2
string="HEREISKEY some_important_string HEREISVALUE some_value"

sed

sed的使用方法比较特别,需要遵守 s/regexp/replacement/flags 的使用模版参考文档

  1. \1 表示("some_(.+)") 匹配的内容
  2. \2 表示(.+)匹配的内容

代表将表达式 “^.* ("some_(.+)") .*” 匹配到的字符替换为 “\1” 也就是 “("some_(.+)")” 并输出

1
2
echo "HEREISKEY \"some_important_string\" HEREISVALUE \"some_value\"" | sed -E "s/^.* (\"some_(.+)\") .*/\1/"

grep

grep不像sed一样可以使用 -E 参数来表达正则,而不用对大部分符号使用转义符

1
2
echo "HEREISKEY \"some_important_string\" HEREISVALUE \"some_value\"" | grep -o -E "\"some_(.+)\"\s"

BASH_REMATCH

该方法为自带表达式 推荐使用这一种 其思想和 sed一样,是按照顺序将结果放入数组

| 数组下标 | 匹配表达式 | 匹配结果 |
| :————- | :————- |
| BASH_REMATCH[0] | ^.( "some_(.+)" ). | HEREISKEY “some_important_string” HEREISVALUE “some_value” |
| BASH_REMATCH[1] | ( "some_(.+)" ) | “some_important_string” |
| BASH_REMATCH[2] | (.+) | important_string |

1
2
if [[ "HEREISKEY \"some_important_string\" HEREISVALUE \"some_value\"" =~ ^.*( \"some_(.+)\" ).* ]] ; then echo ${BASH_REMATCH[1]}; fi

三者区别

命令 思想
sed、BASH_REMATCH 先匹配全文,然后将自表达式匹配结果依次放入index
grep 直接截取表达式匹配到的部分,并不会把自表达式放入index
  • Shell
  • Tips

展开全文 >>

Shell三连(一):脚本参数设定和解析

2018-12-01

心路历程

Shell的参数解析分为两种

  1. 直接从运行行取参数 $0 $1这种
  2. 进行复杂的参数分析,使用 getopts

getopts的内置参数

根据查询可知 getopts is defined in POSIX®. ,我们找到了一个参考页面,很多关于getopts的讲解里,都说到了两个变量 OPTIND 和 OPTARG, 是两个全局变量,一个代表getopts当前读取到的Index,一个是当前读取到的变量的值

OPTIND

1
2
3
4
5
6
OPTIND=1

...

shift "$((OPTIND-1))"

其中OPTIND代表的意思就是 Holds the index to the next argument to be processed,OPTIND is initially set to 1, and needs to be re-set to 1 if you want to parse anything again with getopts 等于1的原因是第0个是getopts命令行本身,和$0一个原理

shift的作用

位置参数可以用shift命令左移。比如shift 3表示原来的$4现在变成$1,原来的$1、$2、$3丢弃

在执行完 getopts后边可能还会执行,需要把解析过的参数丢弃,所以加上shift “$((OPTIND-1))”

使用方法和OPTARG

  1. 调用getopts方法
  2. 然后对getopts的结果进行while循环

getopts 后根据顺序可以接三个参数 getopts OPTSTRING VARNAME [ARGS…]

参数 作用
OPTSTRING 需要解析的参数
VARNAME 每次解析到的参数
ARGS 如果shell脚本不输入任何参数,则使用这个为默认输入
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
OPTIND=1

while getopts ":a:bc" opt; do
case $opt in
a)
echo "-a was triggered, Parameter: $OPTARG"
;;
b)
echo "-b was triggered, Parameter: $OPTARG"
;;
c)
echo "-c was triggered, Parameter: $OPTARG"
;;
\?)
echo "Invalid option: -$OPTARG"
exit 1
;;
:)
echo "Option -$OPTARG requires an argument."
exit 1
esac
done

shift "$((OPTIND-1))"

colon 冒号的作用

在OPTSTRING中如果想对哪个参数后边可以跟一个值,只需要在其后边加冒号 “:” 就可以了,如果开头就是冒号,代表静默异常模式,就是一旦参数异常不出发 “?” Invalid option

如何使用单词参数

根据Stack Overflow回答 getopts 并不提供单词参数的解析能力,所可以通过遍历参数列表+Shift切换的模式进行解析

  1. 首先把长参数转化为短参数,使用到了 set
  2. 然后把短参数根据 getopts 解析

有关 set – “$@” “-h” 指令的含义,参考Bash的内置命令set,加入 – 是为了保证 $@ 不会被当成可选字段 [–abefhkmnptuvxBCEHPT]

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

# Transform long options to short ones
for arg in "$@"; do
shift #切换下一个
case "$arg" in
"--help") set -- "$@" "-h" ;;
"--rest") set -- "$@" "-r" ;;
"--ws") set -- "$@" "-w" ;;
*) set -- "$@" "$arg"
esac
done

# Default behavior
rest=false; ws=false

# Parse short options
OPTIND=1
while getopts "hrw" opt
do
case "$opt" in
"h") print_usage; exit 0 ;;
"r") rest=true ;;
"w") ws=true ;;
"?") print_usage >&2; exit 1 ;;
esac
done

# remove options from positional parameters

shift $(expr $OPTIND - 1)

  • Shell
  • Tips

展开全文 >>

Python三连(五):相等和类型判断的细节

2018-10-05

指针相等、值相等

Python中存在 is 和 == 两种相等,和Java、OC不同的是含义恰好不一样

语言 值相等 地址相等(实例相等)
Python == is
Java equals() ==
OC isEqual ==

类判断、实例判断

Python中也存在 isinstance() 和 type() 两个对类型判断的方法, 对应Java和OC的是

语言 值相等 地址相等(实例相等)
Python isinstance(obj, clazz) type(obj) is clazz
Java obj instanceof clazz object.getClass() != clazz.class
OC isKindOf isMemeberOf
  • Python
  • Tips

展开全文 >>

Python三连(四):获取键盘输入到变量

2018-10-04

Python 2.x 和 3.x 的区别

在Python 2.x 中存在两个获取Keyboard Input的函数,一般来讲都要用 raw_input()

  1. input()
  2. raw_input()

其根据教程解释区别关键在于是否读取一个合法的python类型,如果时非法python类型,会报错

1
2
3
4
5
6
7
8
9
10
11
# 读取input的内容赋值
name = input("Enter your name: ")
# 输入 somename 注意不要带引号
print(name)

# 直接报错, 因为会将 somename 作为一个变量解析
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<string>", line 1, in <module>
NameError: name 'somename' is not defined

而在Python 3.x 中,则直接取消了raw_input(),把原本的input改为了同样的功能

因为input()函数在2.x中几乎没人用

结论

在Python3.x 中直接使用input(), 如果是2.x则使用 raw_input()

  • Python
  • Tips

展开全文 >>

Python三连(三):Json的读写

2018-10-03

Json库的使用

Json库的输入和输出函数分别是,最后s的区别是代指 string

  1. load(s) : 把File或者JsonString装载到Python运行时Dict对象
  2. dump(s) : 把对象输出到File或者JsonString
1
2
3
4
5
6
7
8
9
10
11
12
import json

dictionary = {
"key": "This is Key",
"value": "This is Value",
"sub": {
"key": "Sub Key",
"value": "Sub Value"
}
}


Json对String的读写

主要是使用dumps和loads方法来完成

1
2
3
4
5
6
json_sting = json.dumps(dictionary)
runtime_dict = json.loads(json_sting)

print("json_sting Type: %s\nruntime_dict Type: %s" % (str(type(json_sting)), str(type(runtime_dict))))
print(json_sting)

Json和File的读写

主要是使用dump和load方法来完成,注意如果file被open之后,需要json.load则不能运行read() 或者 readlines() 方法

1
2
3
4
5
6
7
8
9
10
filo_write = open("./strings.json", "w+")
json.dump(dictionary, filo_write)
filo_write.close()

filo_read = open("./strings.json", "r")
runtime_dict = json.load(filo_read)
filo_read.close()

print("runtime_dict Type: %s" % str(type(runtime_dict)))
print(runtime_dict)

格式调整

如果使用默认格式,dump出的Json字符串是没有换行的,所以我们可以使用两个参数来调整格式

参数 作用
indent 控制缩进
separators 用一个2纬元组控制逗号加不加空格,以及冒号前后的空格
1
print(json.dumps(dictionary, indent=4, separators=(',', ' : ')))
  • Python
  • Tips

展开全文 >>

&laquo; Prev1…34567…45Next &raquo;
© 2021 Alan Li
Hexo Theme Yilia by Litten
  • 所有文章
  • 关于我

tag:

  • iOS
  • Java
  • Collection
  • Python
  • Shell
  • CMake
  • Memory
  • JavaScript
  • Architecture
  • AnchorPoint
  • Android
  • Web
  • Annotation
  • AFNetworking
  • Window
  • ViewController
  • AutoLayout
  • Dozer
  • CoreAnimation
  • Cycle Retain
  • Block
  • UI
  • IDE
  • FrontEnd
  • CSS
  • Category
  • TableViewCell
  • Security
  • Net
  • JSP
  • Spring
  • C
  • MyBatis
  • Date
  • React
  • GCD
  • UITouch
  • Gesture
  • UIControl
  • Git
  • HTML
  • HTTPS
  • HTTP
  • Servlet
  • Server
  • DataBase
  • MySQL
  • Linux
  • Tutorial
  • Ajax
  • Type
  • JQuery
  • JSON
  • Exception
  • Parameter
  • Reflect
  • Thread
  • Sort
  • KVO
  • MKMapKit
  • Overlay
  • Maven
  • Configure
  • Tips
  • Transaction
  • Swift
  • NavigationBar
  • Nginx
  • Runtime
  • OpenCV
  • Property
  • Playground
  • Protocol
  • Redux
  • ScrollView
  • Session
  • Cookie
  • Shiro
  • Error
  • Singleton
  • RegEx
  • StackView
  • StatusBar
  • Base64
  • Socket
  • TCP
  • IP
  • TextField
  • CALayer
  • UILabel
  • View
  • Animation
  • Xcode
  • Hexo
  • Terminal
  • OC
  • Device
  • Log
  • Image
  • JUnit
  • Oval
  • Archive
  • XSS
  • Compiler
  • Aspect
  • Responder
  • Class
  • FireWall
  • RetainCount
  • Const
  • Frame
  • String
  • Symbols
  • Framework
  • CocoaPods
  • Unity
  • Message
  • Button
  • AuthorizationStatus
  • Struct
  • XCTest
  • NSNotification
  • Contact

    缺失模块。
    1、请确保node版本大于6.2
    2、在博客根目录(注意不是yilia根目录)执行以下命令:
    npm i hexo-generator-json-content --save

    3、在根目录_config.yml里添加配置:

      jsonContent:
        meta: false
        pages: false
        posts:
          title: true
          date: true
          path: true
          text: false
          raw: false
          content: false
          slug: false
          updated: false
          comments: false
          link: false
          permalink: false
          excerpt: false
          categories: false
          tags: true
    

我写的,大概率是错的。。。。。