Linux 스크립트(쉘)에 대한 자세한 설명

개요

스크립트 : 본질적으로 특정 형식으로 명령어를 저장하는 파일로, 시스템은 스크립트 파서를 사용하여 명령어를 번역하거나 구문 분석하고 실행할 수 있습니다(컴파일할 필요 없음).

쉘은 C로 작성된 응용 프로그램인 동시에 스크립팅 언어(Application Parsing Scripting Language)입니다.

Shell은 사용자가 운영 체제 커널 서비스에 액세스하는 인터페이스를 제공합니다.

Ken Thompson의 sh는 최초의 Unix 셸이며 Windows 탐색기는 일반적인 그래픽 인터페이스 셸입니다.


쉘 프로그래밍은 코드를 작성할 수 있는 텍스트 편집기와 해석하고 실행할 수 있는 스크립트 인터프리터가 있는 한 JavaScript 및 PHP 프로그래밍과 동일합니다.

Linux용 셸 명령 구문 분석기에는 여러 유형이 있으며 일반적인 구문 분석기는 다음과 같습니다.

  • 본 셸(/usr/bin/sh 또는 /bin/sh)
  • Bourne Again Shell(/bin/bash)(대부분의 Linux 시스템에서 기본 쉘)
  • C 쉘(/usr/bin/csh)
  • K 쉘(/usr/bin/ksh)
  • 루트 쉘(/sbin/sh)

이 문서는 사용 편의성과 무료 비용으로 인해 일상 업무에서 널리 사용되는 Bourne Again Shell인 Bash 에 중점을 둡니다. 동시에 Bash는 대부분의 Linux 시스템의 기본 셸이기도 합니다. Linux 시스템의 기본 파서 명령 보기: echo $SHELL

일반적으로 사람들은 Bourne Shell과 Bourne Again Shell을 구분하지 않으므로 #!/bin/sh 와 같이 #!/bin/bash 로 변경할 수도 있습니다 .


상세한 문법

셸 스크립트 파일을 작성할 때 처음에 줄을 추가하십시오: #!/bin/bashLinux에는 파서로 bash뿐만 아니라 다른 파서도 있고 이들 사이의 구문이 다소 다를 수 있으므로 시스템에 이 파서를 사용하도록 알리기 위해 이 문장을 추가하는 것이 가장 좋습니다.

#! 는 후속 경로로 지정된 프로그램이 이 스크립트 파일을 해석하는 쉘 프로그램임을 시스템에 알리는 규칙 표시입니다.

알아채다:

  • 쉘 스크립트에 여러 명령을 래핑할 때 명령은 위에서 아래로 실행되며, 위의 명령이 잘못 실행되더라도 다음 명령은 계속 실행됩니다.

  • 쉘 스크립트에서 같은 줄에 여러 명령어를 작성할 때는 세미콜론( ; )을 사용하여 구분하며, 앞에 쓴 명령어가 실행에 실패하더라도 뒤에 쓴 명령어는 계속해서 실행된다.


수학 표현

(( ))쉘 수학적 계산 명령으로 C++, C#, Java 및 기타 프로그래밍 언어와 달리 쉘에서 데이터 계산을 수행하는 것이 그리 편리하지 않으며 특수한 수학적 계산 명령을 사용해야 하며 (( ))도 그 중 하나입니다.

+	 	# 加
-	 	# 减
*	 	# 乘
/	 	# 除
%	 	# 取余
**	 	# 幂

쉘 변수

변수 분류

목적에 따라 4가지 유형의 변수로 나눌 수 있습니다(변수의 구분은 책마다 다릅니다).

  • 환경 변수 : 시스템 커널, 시스템 명령, 응용 프로그램의 운영 환경을 제공하기 위해 설정한 변수들의 집합체

  • 내부 변수 : 쉘용으로 특별히 설정된 변수 세트를 총칭하는 용어

  • 매개변수 변수 : 매개변수로 전달되는 데이터. $1 $2위치 매개변수는 ... $N및 쉘 내부 변수(예: 등)로 $? $@참조 할 수 있는 함수, 명령문 블록 등에 전달된 데이터입니다.

  • 사용자 정의 변수 : 사용자가 직접 설정한 변수. 지역 변수와 전역 변수로 나눌 수 있습니다.

    • 지역 변수 : 코드 블록이나 함수에서만 유효하고 코드 블록이나 함수를 벗어나면 사라지는 변수.

      코드 블록 또는 함수에서 선언된 로컬 변수는 로컬에서 선언해야 합니다. 그렇지 않으면 현재 셸 프로세스에서도 볼 수 있습니다.

    • 전역 변수 : 스크립트에 정의되어 현재 쉘 스크립트에서만 유효하며 다른 쉘 스크립트 프로세스에서는 접근할 수 없으며 그 범위는 정의된 위치부터 스크립트의 끝 또는 표시되고 삭제되는 곳까지이다.

      전역 변수는 내보내기를 통해 선언된 임시 환경 변수 로 업그레이드할 수 있으므로 현재 프로세스의 자식 프로세스도 이 변수를 사용할 수 있습니다.

      임시 환경변수는 실행 중인 환경에서만 유효하며, 다른 쉘 스크립트가 실행되면 이 임시 환경변수는 무력해진다.


환경 변수와 내부 변수의 차이점 및 사용 (자세한 내용: http://blog.sina.com.cn/s/blog_655047c00100hiao.html):

  • 같은:

    • 둘 다 쉘이 시작되자마자 로드됩니다.
    • 그들은 모두 $ 참조와 일치하며 처음부터 스크립트에 모두 존재하므로 사용자가 다시 설정할 필요가 없습니다.
  • 다른:

    • 환경 변수를 추가, 수정하고 사용자가 재정의할 수 있습니다(자세한 내용: https://blog.csdn.net/LLZK_/article/details/53813266).
    • 쉘 내부 변수는 변경할 수 없습니다.

환경 변수

환경 변수는 하나 이상의 응용 프로그램이 사용할 정보를 포함하는 운영 체제의 특정 이름을 가진 개체입니다.

Linux는 다중 사용자 운영 체제입니다.각 사용자는 시스템에 로그인할 때 전용 운영 환경을 갖습니다.일반적으로 각 사용자의 기본 환경은 동일합니다. 이 기본 환경은 환경 변수 세트의 정의입니다. 각 사용자는 환경 변수를 수정하여 자신의 실행 환경을 구성할 수 있습니다.

환경 변수는 셸과 밀접한 관련이 있으며 사용자가 시스템에 로그인하면 셸이 시작되는데, 리눅스의 경우 일반적으로 bash(Bourne Again 셸, Bourne 셸(sh)의 확장)이며 다른 버전의 셸로 전환할 수도 있습니다.

bash에는 /etc/bashrc 및 /etc/profile의 두 가지 기본 시스템 수준 구성 파일이 있습니다. 이러한 구성 파일에는 쉘 변수와 환경 변수라는 두 가지 변수 세트가 포함되어 있습니다. 쉘 변수는 로컬 변수이고 환경 변수는 전역 변수입니다. 환경 변수는 쉘 명령을 통해 설정됩니다. 설정된 환경 변수는 현재 사용자의 모든 프로그램에서 사용할 수 있습니다.


환경 변수의 분류

  • 환경변수는 생명주기에 따라 영구환경변수임시변수 로 나눌 수 있다.
  • 다양한 사용자 수준에 따라 시스템 수준 변수사용자 수준 변수 로 나눌 수 있습니다.

모든 사용자에게 적용되는 영구 변수(시스템 전체):

이 유형의 변수는 시스템의 모든 사용자에게 적용되며 모든 사용자가 이 유형의 변수를 사용할 수 있습니다. 행동 범위는 전체 시스템입니다.

# 设置方式:
# 使用 vi 命令打开 /etc/profile 文件,用export指令添加环境变量
	
# 步骤示例:
# 1.打开配置文件,并按 i ,进入编辑模式
vi /etc/profile
# 2.在配置文件末尾添加环境变量
export 环境变量名(一般大写)="值"
# 3.使配置文件立即生效
source /etc/profile

# 注意:
	# 1. /etc/profile 只有root(超级用户)才能修改。可以在etc目录下使用 ls -l 查看这个文件的用户及权限
	# 2. 添加新的环境变量并退出配置文件后,需要执行命令 source /etc/profile 后才会立即生效。否则在下次重进此用户时才能生效

단일 사용자(사용자 수준)에 적용되는 영구 변수

이 유형의 환경 변수는 현재 사용자에게만 영구적으로 적용됩니다. 즉, 사용자 A가 이러한 환경 변수를 설정하면 A만 이 환경 변수를 사용할 수 있습니다. 그리고 다른 B, C, D, E... 사용자 등의 경우에는 이 변수가 존재하지 않습니다.

# 设置方法:在用户主目录”~”下的隐藏文件 “.bashrc”中添加自己想要的环境变量

# 步骤示例:
# 1.打开配置文件,并按 i ,进入编辑模式
vi ~/.bashrc
# 2.在配置文件末尾添加环境变量
export 环境变量名(一般大写)="值"
# 3.使配置文件立即生效
source ~/.bashrc

# 注意:
	# 系统中可能存在两个文件,.bashrc和.bash_profile(有些系统中只有其中一个)
	# 原则上来说设置此类环境变量时在这两个文件任意一个里面添加都是可以的。二者设置大致相同
      # ~/.bash_profile 是交互式login方式进入bash shell运行。即 .bash_profile 只会在用户登录的时候读取一次
      # ~/.bashrc 是交互式non-login方式进入bash shell运行。即 .bashrc 在每次打开终端进行一次新的会话时都会读取

# 查看隐藏文件(.XXX):
	# 方式1:命令 ls -al
	# 方式2:命令 echo .*

일시적으로 유효한 환경 변수(현재 셸에만 유효)

임시 환경 변수의 범위는 현재 셸 스크립트와 현재 프로세스의 하위 프로세스 셸입니다. 현재 쉘 스크립트를 종료하고 사라짐

# 设置方法:直接使用export指令添加。 

환경 변수에 대한 공통 지시문

# 查看显示环境变量:echo,变量使用时要加上符号“$”
#例:
echo $PATH

# 设置新的临时环境变量 export
export 新临时环境变量名=内容 
# 例:
export MYNAME=”LLZZ”

# 修改环境变量没有指令,可以直接使用环境变量名进行修改。 
# 例:
MYNAME=”ZZLL”

# 查看所有环境变量
env

# 查看本地定义的所有shell变量
set
    
# 删除一个环境变量
unset 变量名
# 例:
unset MYNAME

일반적으로 사용되는 환경 변수(모두 대문자)

  • PATH : 명령의 검색 경로를 봅니다. 환경 변수 PATH를 설정하면 프로그램이나 명령을 보다 편리하게 실행할 수 있습니다.
# 查看环境变量PATH
echo $PATH
# 说明:
	# 每一个冒号都是一个路径,这些搜索路径都是一些可以找到可执行程序的目录列表。
	# 当输入一个指令时,shell会先检查命令是否是内部命令,不是的话会再检查这个命令是否是一个应用程序。
	# 然后shell会试着从搜索路径,即PATH中寻找这些应用程序。
	# 如果shell在这些路径目录里没有找到可执行文件。则会报错。
	# 若找到,shell内部命令或应用程序将被分解为系统调用并传给Linux内核。

# 示例: 
# 现在有一个c程序test.c通过gcc编译生成的可执行文件a.out(功能:输出helloworld)。平常执行这个a.out的时候是使用 
  # 方式1:相对路径调用:./a.out  (”.”代表当前目录,”/”分隔符)
  # 方式2:绝对路径调用:/home/lzk/test/a.out 
  # 方式3:通过设置PATH环境变量,直接用文件名调用: a.out (只要可以通过PATH中路径找得到这个可执行文件)
  
# 使用export指令添加PATH中的路径
# 示例:将a.out的路径添加到搜索路径当中
export PATH=$PATH:路径   		# PATH中路径是通过冒号“:”进行分隔的,把新的路径加在最后就OK
  • HOME : 사용자가 Linux 시스템에 로그인할 때 기본 디렉토리인 사용자의 기본 작업 디렉토리, 즉 "~"를 지정합니다.

  • HISTSIZE : 이력 명령 레코드 수를 저장합니다.

    사용자가 입력한 명령은 시스템에 저장되며 이 환경 변수는 유지된 명령의 수를 기록합니다. 일반적으로 1000

    이러한 기록 명령은 사용자의 작업 홈 디렉토리 "~" 아래에 있는 숨겨진 파일 .bash_profile에 저장됩니다.

    명령 기록으로 볼 수 있습니다.

  • LOGNAME : 현재 사용자의 로그인 이름을 의미합니다.

  • HOSTNAME : 호스트의 이름을 나타냅니다.

  • SHELL : 현재 사용자가 사용하고 있는 쉘을 의미

  • LANG/LANGUGE : 언어 관련 환경변수, 다국어 사용자가 수정할 수 있는 환경변수

  • MAIL : 현재 사용자의 메일 저장 디렉토리를 의미

  • PS1 : 첫 번째 수준의 Shell 명령 프롬프트, 루트 사용자는 #이고 일반 사용자는 $입니다.

  • PS2 : 두 번째 수준의 Shell 명령 프롬프트, 기본값은 ">"

  • PS3 : 세 번째 수준의 셸 명령 프롬프트입니다. 선택 루프 제어 구조에 대한 메뉴 선택 프롬프트에 주로 사용됨

  • TMOUT : 사용자 및 시스템 상호 작용에 대한 시간 초과 값

    시스템이 사용자와 상호 작용할 때 시스템은 사용자에게 입력하라는 프롬프트를 표시하지만 사용자가 오랫동안 입력하지 않으면 TMOUT에서 설정한 값을 초과한 후 시간 초과로 인해 쉘이 실행을 종료합니다.


쉘 내부 변수

위치 변수(파라미터 변수)

쉘 스크립트를 실행할 때 명령줄에서 전달된 매개변수 정보를 얻으려면 다음과 같은 위치 변수를 사용해야 합니다. ./myshell.sh 100 200은 쉘 스크립트의 매개변수 전달 방법으로 이해할 수 있습니다.

# 预定义变量		# 功能描述
$n			# n为数字
			  # $0表示命令本身(执行脚本的命令)
			  # $1-9代表第一个参数到第九个参数
			  # 10以上的参数需要使用大括号进行包裹如:${10}
$*			# 传递给函数或脚本的所有参数
$@			# 传递给函数或脚本的所有参数
$#			# 代表参数的个数

# 注:
	# $* 和 $@ 都表示传递给函数或脚本的所有参数,不被双引号(" ")包含时,都以"$1" "$2" … "$n" 的形式输出所有参数。
	# 但是当它们被双引号(" ")包含时,
		# "$*" 会将所有的参数作为一个整体,以"$1 $2 … $n"的形式输出所有参数;
		# "$@" 会将各个参数分开,以"$1" "$2" … "$n" 的形式输出所有参数

미리 정의된 변수

미리 정의된 변수: 셸 설계자가 미리 정의한 변수로 셸 스크립트에서 직접 사용할 수 있습니다.

# 预定义变量		# 功能描述
$?			# 命令执行后返回的状态
$$			# 当前进程的进程号(PID)
$! 			# 最近运行的一个后台进程的进程号(PID)
$?			# 最后一次执行的命令的返回状态
			  # 若返回 0 :则上一个命令正确执行;若返回 非0(具体数值由命令自己决定),则上一个命令未正常执行

$LINENO		# 调测用。用于显示脚本中当前执行的命令的行号
$OLDPWD		# 配合cd命令改换到新目录之前所在的工作目录
			  # 用法:cd $OLDPWD  (切换到之前的工作目录,和cd - 功能一样)
$PPID		# 当前进程的父进程的PID
$PWD		# 当前工作目录。等同于命令pwd的输出
$RANDOM		# 随机数变量。每次引用这个变量会得到一个0~32767的随机数
$REPLY		# 通过read命令读入的数据,如果没有被赋值指定变量,则默认赋值到 REPLY 变量中
$SECONDS	# 脚本已经运行的时间(以秒为单位)

맞춤 변수: 정의, 할당

변수는 모든 프로그래밍 언어의 필수적인 부분이며 변수는 다양한 데이터를 저장하는 데 사용됩니다. 일반적으로 스크립팅 언어는 변수를 정의할 때 타입을 지정할 필요 없이 직접 값을 할당하면 되고 Shell 변수도 이 규칙을 따른다.

Bash 셸에서 각 변수의 값은 문자열이며 변수에 따옴표를 지정했는지 여부에 관계없이 값은 문자열 형태로 저장됩니다.

쉘 변수는 일부 프로그래밍 언어와는 다른 것으로 일반적으로 값을 할당할 때는 쉘 변수를 포함하지 않아도 되지만 을 “$”사용하거나 출력할 때는 포함해야 합니다 “$”. 더하기, 빼기, 곱하기 및 나누기를 할 때 이중 괄호를 사용하십시오. 괄호 밖에 하나 있어야 하며 “$”괄호 안의 변수는 생략할 수 있습니다 “$”.


변수 정의

Shell은 변수를 정의하는 다음 세 가지 방법을 지원합니다.

variable=value
variable='value'
variable="value"

설명하다:

  • variable은 변수 이름, value는 변수에 할당된 값

  • 값에 공백(예: 공백, 탭 들여쓰기 등)이 포함되어 있지 않으면 따옴표를 사용할 수 없습니다.

  • 값에 공백 문자가 포함된 경우 작은따옴표와 큰따옴표로 묶어야 합니다.

    분석: 명령어를 읽은 후 공백에 따라 문자열이나 키워드를 잘랐다가 잘린 후에는 and, 변수 할당 으로 c=he이해 되지만 일치하는 항목을 찾을 수 없고 해당 명령어를 불러올 수 없어 이 오류가 출력됩니다.lloc=hellollo

  • 쉘 스크립트의 유일한 변수 유형은 정수와 문자열입니다.

알아채다:

  • 할당 번호 주변에는 공백이 없어야 합니다 =. 그렇지 않으면 명령으로 구문 분석되며 이러한 명령은 오류로 보고되지 않습니다. 대부분의 일반적인 프로그래밍 언어에서는 그렇지 않을 수 있습니다.

쉘 변수의 명명 규칙:

  • 변수 이름은 숫자, 문자 및 밑줄로 구성됩니다.
  • 문자 또는 밑줄로 시작해야 합니다.
  • 셸에 있는 키워드는 사용할 수 없습니다(예약된 키워드는 help 명령을 통해 볼 수 있음).

작은따옴표와 큰따옴표의 차이점:

변수를 정의할 때 변수 값은 작은따옴표 ' '와 큰따옴표 로 묶습니다 " ".

  • 변수의 값을 작은 따옴표 ' '로 묶으면 작은 따옴표 안에 있는 것이 무엇이든 출력되며, 내용에 변수와 명령이 있어도(명령어는 뒤집어야 함) 그대로 출력됩니다. 이 방법은 순수 문자열, 즉 변수, 명령 등을 구문 분석하지 않으려는 시나리오를 정의하고 표시하는 데 더 적합합니다.

  • 변수의 값을 큰따옴표 로 묶으면 큰 " "따옴표 안에 있는 변수명과 명령어를 그대로 출력하지 않고 내부의 변수와 명령어를 먼저 파싱하여 출력한다. 이 방법은 문자열에 연결된 변수 및 명령이 있고 출력하기 전에 구문 분석하려는 변수 정의에 더 적합합니다.

제안:

  • 변수의 내용이 숫자인 경우 따옴표로 묶을 수 있습니다.
  • 그대로 출력해야 하는 경우 작은 따옴표를 추가하십시오.
  • 특별한 요구 사항이 없는 다른 문자열에 대해서는 큰따옴표를 추가하는 것이 가장 좋습니다. 변수를 정의할 때 큰따옴표를 추가하는 것이 가장 일반적인 사용 시나리오입니다.

예:

#!/bin/bash

a=10
b=20
c="this is a test"
d=$((a+b))
f=test					# 变量赋值的时候如果只有一个单词可以不用加引号
time=`date`				# date 命令用来获得当前的系统时间
date=`date +%s`    		# data 命令的 %s 格式控制符可以得到当前的 UNIX 时间戳,可以用于计算脚本的运行时间
							# UNIX 时间戳是指从 1970 年 1 月 1 日 00:00:00 到目前为止的秒数

echo $c					
echo "a = "$a          # 输出a的
echo "a+b = "$((a+b))  # 输出a+b的值
echo $((a+b*a-b/a+a%b+a**2)) #表达式可以很长

변수 할당

# 方式1:“=”并初始化
var=value  		# 注意:如果value是带有空格的字符串,需要加单或双引号

# 方式2:“=”不初始化
var=			# 未赋值变量,值为null

# 方式3:read命令
# read命令是读取标准输入的数据,然后存储到指定的变量中。注意:read接收的是标准输入而不是参数,read命令是不接收参数的。

맞춤 변수: 참조, 수정, 삭제

변수 참조

# 方式1
$variable

# 方式2(变量名外面的花括号 { }是可选的,加不加都行,加花括号是为了帮助解释器识别变量的边界)。推荐
${variable}

# 方式3$variable”或“${variable}# 注:引用变量后,双引号会对于引用结果中空格和一些特殊符号进行的解析或者不解析。而引用结果用的空格在命令中的分隔作用会完全改变一个命令的输出,而特殊符号的是否解析也会影响最终的输出结果。
skill="Java"
echo "I am good at ${skill}Script"
# 如果不给 skill 变量加花括号,写成`echo "I am good at $skillScript"`,解释器就会把 $skillScript 当成一个变量(其值为空),代码执行结果就不是我们期望的样子了。

변수 값 수정

다음과 같이 정의된 변수를 재할당할 수 있습니다.

url="http://c.biancheng.net"
echo ${url}
# 第二次对变量赋值时不能在变量名前加 $,只有在使用变量时才能加 $
url="http://c.biancheng.net/shell/"
echo ${url}

변수 삭제

변수는 unset 명령을 사용하여 삭제할 수 있습니다 .

문법:

unset variable_name

알아채다:

  • 변수가 삭제되면 다시 사용할 수 없습니다.
  • unset 명령은 읽기 전용 변수를 삭제할 수 없습니다.

예:

#!/bin/sh
myUrl="http://c.biancheng.net/shell/"
unset myUrl
echo $myUrl				# 会没有任何输出

맞춤 변수: 읽기 전용 설정

readonly 명령을 사용하여 변수를 읽기 전용 변수로 정의하고 읽기 전용 변수의 값은 변경할 수 없습니다.

다음 예에서는 읽기 전용 변수를 변경하려고 시도하고 오류가 발생합니다.

#!/bin/bash

myUrl="http://c.biancheng.net/shell/"
readonly myUrl
myUrl="http://c.biancheng.net/"				# 会报错

쉘 명령 대체: 명령 결과를 변수에 할당

Shell은 또한 명령의 실행 결과를 변수에 할당하는 것을 지원합니다.두 가지 일반적인 방법이 있습니다.

# 两种方式可以完成命令替换,一种是$(),一种是反引号` `
variable=$(commands)
variable=`commands`
# 说明:
	# 1.variable 是变量名,commands 是要执行的命令
	# 2.commands 可以只有一个命令,也可以有多个命令,多个命令之间以分号;分隔

알아채다:

  • 대체된 명령의 출력에 여러 줄이 포함되거나(즉, 줄 바꿈 문자가 있음) 여러 개의 연속 공백 문자가 포함된 경우 변수를 출력할 때 변수를 큰따옴표로 묶어야 합니다. 그렇지 않으면 시스템이 기본 공백 문자를 사용하여 채울 것이므로 줄 바꿈이 유효하지 않게 되고 연속 공백 문자가 하나로 압축되어 형식이 혼동됩니다.

  • 두 가지 형태의 변수 대체는 동일하며 마음대로 사용할 수 있습니다.

  • 백틱과 작은따옴표는 매우 유사하여 혼동을 일으키기 쉬우므로 이 방법은 권장되지 않습니다.

    용도는 비교적 명확하며 중첩 지원 과 같은 $() 일부 경우에 사용해야 하며 백틱은 허용되지 않습니다.$()$()

  • $()Bash 셸에서만 유효하며 백틱은 많은 셸에서 작동합니다.


쉘 변수 표현식

# 	表达式				  # 	说明
${
    
    #string}				# 计算$string的长度
${string:position}		# 从pos位置开始提取字符串
${string:position:len}	# 从pos位置开始提取长度为len的字符串
${string#substr}		# 从开头删除最短匹配子串
${string##substr}		# 从开头删除最长匹配子串
${string%substr}		# 从结尾删除最短匹配子串
${string%%substr}		# 从结尾删除最长匹配子串

 # 注意:字符串的长度包括空格,但是没有像C语言中那种'\0'字符

#!/bin/bash

str="a b c d e f g h i j"

echo "the source string is "${str}                         #源字符串
echo "the string length is "${
    
    #str}                        #字符串长度
echo "the 6th to last string is "${str:5}                  #截取从第五个后面开始到最后的字符
echo "the 6th to 8th string is "${str:5:2}                 #截取从第五个后面开始的2个字符
echo "after delete shortest string of start is "${str#a*f} #从开头删除a到f的字符
echo "after delete widest string of start is "${str##a*}   #从开头删除a以后的字符
echo "after delete shortest string of end is "${str%f*j}   #从结尾删除f到j的字符
echo "after delete widest string of end is "${str%%*j}     #从结尾删除j前面的所有字符包括j

쉘 테스트 판정: 테스트, [ ], [[ ]]

Shell의 test 명령어와 [ ]는 특정 조건이 참인지 확인하는 데 사용되며 수치, 문자, 파일의 세 가지 측면에서 테스트를 수행할 수 있습니다.

[[ ]]는 bash 프로그래밍 언어의 키워드입니다. 명령이 아닌 [[ ]] 구조는 [ ] 구조보다 더 일반적입니다. [[ 및 ]] 사이의 모든 문자는 파일 이름 확장 또는 단어 분할을 거치지 않지만 매개변수 확장 및 명령 대체를 거치게 됩니다. 문자열의 패턴 일치를 지원하고 =~ 연산자를 사용할 때 셸 정규식도 지원합니다. 문자열을 비교할 때 오른쪽은 [[ hello == hell? ]]와 같이 단순한 문자열이 아닌 패턴으로 사용할 수 있으며 결과는 true입니다. [[ ]] 따옴표 없이 문자열 또는 와일드카드와 일치합니다.

[ ] 대신 [[ ]] 조건 구문을 사용하면 스크립트에서 많은 논리 오류를 방지할 수 있습니다. 예를 들어 &&, ||, <, > 연산자는 [[ ]] 조건 판단 구조에 정상적으로 존재할 수 있지만 [ ] 구조에 나타날 경우 오류가 발생합니다. if [[ $a !=1 && $a != 2 ]]예를 들어 직접 사용 하거나 이중 괄호를 if [ $a -ne 1] && [ $a != 2 ]사용 하지 않는 경우에 사용할 수 있습니다 if [ $a -ne 1 -a $a != 2 ].

bash는 이중 대괄호로 묶인 표현식을 단일 요소로 취급하고 종료 상태 코드를 반환합니다.

참고: [ ] 사용 시 각 변수 사이에 공백이 있어야 하며, 좌우 대괄호 사이에 공백이 있어야 합니다. 그렇지 않으면 오류가 보고됩니다.

수치 테스트

매개변수 설명하다
-eq 같으면 참
- 이다 같지 않으면 참
-gt 보다 크면 참
-ge 크거나 같으면 참
-lt 미만이면 참
- 작거나 같으면 참

문자열 테스트

매개변수 설명하다
= 같으면 참
!= 같지 않으면 참
-z 문자열 문자열 길이가 0이면 참
-n 문자열 문자열의 길이가 0이 아니면 참

파일 테스트

매개변수 설명하다
-e 파일 이름 파일이 존재하면 참
-f 파일 이름 파일이 존재하고 일반 파일이면 참
-d 파일 이름 파일이 존재하고 디렉토리이면 참
-r 파일 이름 파일이 존재하고 읽을 수 있으면 참
-w 파일 이름 파일이 존재하고 쓰기 가능한 경우 True
-x 파일 이름 파일이 존재하고 실행 가능한 경우 참
-s 파일 이름 파일이 존재하고 하나 이상의 문자가 있는 경우 참
-c 파일 이름 파일이 존재하고 문자 특수 파일인 경우 참
-b 파일 이름 파일이 존재하고 블록 특수 파일인 경우 참

#!/bin/bash

# 文件测试
echo "Please input two numbers:"
read num1
read num2

echo "num1 = "${num1}
echo "num2 = "${num2}
echo -e "by test\n"
test $num1 -eq $num2 && echo "num1 == num2" || echo "num1 != num2"
echo -e "by []\n"
[ $num1 -eq $num2 ] && echo "num1 == num2" || echo "num1 != num2"


# 数值测试
echo "Please input a filename: "
# 从标准输入获取一个文件名,并存入filename变量中
read filename
echo -e "by test\n"
test -f $filename && echo "这是一个普通文件" || echo "这不是一个普通文件"
echo -e "by []\n"
[ -f $filename ] && echo "这是一个普通文件" || echo "这不是一个普通文件"

논리 연산자: AND, OR, NOT

Shell은 또한 테스트 조건을 연결하기 위해 세 개의 논리 연산자가 아닌 (-a) 또는 (-o)를 제공하며 우선 순위 ! 가장 높고 -a 두 번째이며 -o가 가장 낮습니다.

예:

#!/bin/bash

# 逻辑操作符和字符串测试
echo "Please input a city name: "
# 从标准输入获取一个值,并存入city变量中
read city
if "成都" = $city -o "南京" = $city
then
    echo '城市是成都或南京'
else
    echo '城市既不是成都也不是南京'
fi

쉘 조건부 분기 구조문

단일 분기 문

체재:

if 条件 ; then 结果; fi

# 最后面一定要有fi,在shell脚本里面,控制分支结构结束都要和开头的单词相反,例如,if <–> fi,case <–> esac

#!/bin/bash

echo "Please input a filename"
# read filename:表示从标准输入获取一个文件名,并存入felename变量中
read filename
if [ -f $filename ]
then
	echo "this file is a ordinary file."
fi

이중 분기문

체재:

if 条件 ; then 结果; else 结果; fi

#!/bin/bash

echo "Please input a filename"
read filename
if [ -f $filename ]
then
	echo "this file is a ordinary file."
else
	echo "this file is not a ordinary file."
fi

다분기 판결문

다중 분기 판단에는 두 가지 종류가 있습니다(C 언어와 동일): if-else if 및 case

문법:

if 条件 ; then 结果; elif 条件; then 结果; else 结果; fi

if-else if 예제

#!/bin/bash

echo "Please input your math grades"
read grades

if [ $grades -gt 100 ] || [ $grades -lt 0 ];then
echo "Please input the number range in 0 - 100"
fi

if [ $grades -ge 90 ] && [ $grades -le 100 ]
then
	echo "Your grade is excellent."
elif [ $grades -ge 80 ] && [ $grades -le 89 ];then
	echo "Your grade is good."
elif [ $grades -ge 70 ] && [ $grades -le 79 ];then
	echo "Your grade is middle."
elif [ $grades -ge 60 ] && [ $grades -le 69 ];then
	echo "Your grade is passing."
else
	echo "Your grade is badly."
fi

사례

#!/bin/bash

echo "Please input a command"
read cmd
case $cmd in
cpu)    echo "The cpu information is"
        cat  /proc/cpuinfo;;
mem)    echo "The mem information is"
        cat /proc/meminfo;;
device) echo "The device information is"
        cat /proc/scsi/device_info;;
CD-ROM) echo "The CD-ROM information is"
        cat /proc/sys/dev/cdrom/info;;
*)      echo "Your input command is invalid"
esac

쉘 루프 문

진술을 위해

체재:

for 变量 in 列表
do
语句
done

#!/bin/bash

arr=("0" "1" "2" "3" "4" "5" "6" "7" "8" "9" "a" "b" "c" "e" "e" "f")

# 遍历(不带数组下标。* 和 @ 均可)
for value in ${arr[*]}
do
echo $value
done

# 遍历(带数组下标)
for (( i = 0 ; i < ${#arr[@]} ; i++ ))
do
echo ${arr[$i]}
done

while 문

while문은 조건이 참인 동안 다음 명령문을 실행합니다.

체재:

while 条件
do
语句
done

여기서 조건은 참인 동안을 제외하고는 이렇게 쓸 수 있고, 그 외의 조건은 테스트나 []로 판단해야 한다는 점에 유의해야 한다.

# -----------文件名为test.sh-----------
#!/bin/bash

# $1 为调用脚本时的第1个传参
i=$1
while [ $i -gt 0 ]
do
echo $i
((i--))
done

# -----------调用-----------
sh test.sh 10		# 文件名test.sh 后面跟的是参数,$0代表文件名,$1代表第一个参数...

진술까지

until 문은 조건이 거짓인 동안 다음 문을 실행하는 것입니다.

체재:

until 条件
do
语句
done

#!/bin/bash

i=$1
until [ $i -le 0 ]
do
echo $i
((i--))
done

쉘 기능

체재:

[function] funcName()
{
    
    undefined
语句
[return 返回值]
}

설명하다:

  • 셸 함수 반환의 반환 값은 정수만 가능하며 일반적으로 함수가 성공적으로 실행되었는지 여부를 나타내는 데 사용되며 0은 성공을 나타내고 다른 값은 실패를 나타냅니다. 문자열과 같은 다른 데이터가 반환되면 "숫자 인수 필요"라는 오류 메시지가 보고됩니다.

  • return 返回值는 선택적이며 반환이 없으면 마지막 문의 성공 또는 실패의 상태 값이 기본적으로 반환됩니다.

  • 위치 매개변수는 함수에 매개변수를 전달하는 데 사용됩니다. 함수에서 위치 매개변수 사용: from $1to $n, $0is the file name

함수 호출 방법:

# 方式1:调用函数,然后再使用预定义变量 $? 获取函数返回值
function_name [arg1 arg2 ......]
$?

# 方式2:调用函数并将函数的标准输出赋值到一个变量中。注意:不是返回值
value=`function_name [arg1 arg2 ......]`
value=$(function_name [arg1 arg2 ......])

예:

#!/bin/bash

#打印数字
printNum()
{
    
    
   echo $1				# 位置参数的使用
}

for i in `seq 2 8` 		# seq是一个命令,顺序生成一串数字或者字符
do
printNum $i				# 位置参数的传参
done

함수가 문자열을 출력하는 방법:

백틱을 사용하여 ``함수의 표준 출력을 변수에 할당하고 스크립트는 필요할 때 함수의 출력 값을 얻기 위해 이 변수에 액세스합니다.

참고: 함수에서 표준 출력이 여러 번 수행되면 모든 출력 값이 함께 변수에 할당됩니다. 표준 출력은 함수 내에서 한 번만 수행하는 것이 좋습니다.

#!/bin/bash

# 函数输出字符串
getString()
{
    
    
   echo "abc"
   return 0
}
# 函数输出赋值
value=`getString`
# 使用
echo ${value}-xxxx

쉘 스크립트가 실행되는 방식

(다음 메서드는 스크립트가 절대 경로 또는 상대 경로를 사용할 수 있음을 지정합니다.)

  • Path/xxx.sh : 파일에서 #! 로 지정된 파서에 따라 먼저 파싱하고 #! 로 지정된 파서가 없으면 시스템의 기본 파서를 사용합니다.

    알아채다:

    • chmod +x 文件名이 방법을 사용하려면 실행 파일에 실행 권한(x)( : 파일의 모든 ID에 대한 실행 권한 추가)이 있어야 합니다 . 그렇지 않으면 오류가 보고됩니다.
    • 이런 식으로 스크립트가 현재 경로에 있더라도 다음과 같이 지정해야 합니다. ./xxx.sh
  • bash xxx.sh : bash 파서가 먼저 파싱에 사용되고 bash가 없으면 기본 파서가 사용됨을 나타냅니다.

  • sh xxx.sh : 기본 파서를 직접 사용하여 구문 분석합니다. 상대 경로 또는 절대 경로를 사용할 수 있습니다.

  • .xxx.sh : 기본 구문 분석기를 직접 사용하여 구문 분석 참고: .(점)과 파일 이름 사이에 직접 공백이 있습니다.


확장하다

로컬 IP 주소 스크립트 명령 가져오기

방법 1: IP 주소

네트워크 카드가 여러 개인 경우 첫 번째 IP도 반환

ip addr | awk '/^[0-9]+: / {}; /inet.*global/ {print gensub(/(.*)\/(.*)/, "\\1", "g", $2)}' | sed -n '1p'

쉘 방법 2:ifconfig -a

ifconfig -a | grep inet | grep -v 127.0.0.1 | grep -v inet6 | awk '{print $2}' | tr -d "addr:"

# 命令解析
-  ifconfig -a       和window下执行此命令一样道理,返回本机所有ip信息
-  grep inet           截取包含ip的行
-  grep -v 127.0.0.1    去掉本地指向的那行
-  grep -v inet6        去掉包含inet6的行
-  awk {
    
     print $2}      $2 表示默认以空格分割的第二组 同理 $1表示第一组
-  tr -d "addr:         删除"addr:"这个字符串

다중 NIC

네트워크 카드가 여러 개인 경우 서로 다른 네트워크 세그먼트의 IP가 여러 개 있을 수 있으며, 이때 위의 명령을 계속 실행하면 다음과 같이 여러 IP가 반환됩니다.

특정 기계가 192. .8 및 10. . .* 네트워크 세그먼트의 IP를 가지고 있고 이제 다른 네트워크 세그먼트의 IP 주소에 대해 다른 출력을 인쇄해야 한다고 가정하면 스크립트 다음과 같습니다.

#!/bin/sh
ip=`ifconfig -a|grep inet|grep -v 127.0.0.1|grep -v inet6|awk '{print $2}'|tr -d "addr:"`
echo $ip
if[[ $ip =="10."*]]
then
echo "该网段是10.*.*.*网段"
else
echo "该网段是192.*.*.*网段"
fi

jq 명령: JSON 조작

참고: https://www.cnblogs.com/kumufengchun/p/10799888.html

jq 명령을 사용하면 조각화, 필터링, 변환 등을 포함하여 명령줄에서 직접 JSON에 대한 작업을 수행할 수 있습니다.

jq는 C로 작성되었습니다.

jq의 미리 컴파일된 바이너리 파일은 Linux, OS X 및 Windows 시스템에서 직접 실행할 수 있으며 Linux 시스템에서 yum으로 직접 설치할 수 있습니다.

json 문자열 준비: kumufengchun.json

{
    
    
    "name":"kumufengchun",
    "age":"18",
    "city":"beijing",
    "email":"[email protected]",
    "date":"Thursday",
    "country":"China",
    "company":["baidu","google","alibaba"]
}

json 문자열을 준비합니다.

[
    {
    
    
        "name":"JSON", 
        "good":true
    }, 
    {
    
    
        "name":"XML", 
        "good":false
    }
]

jq의 기본 사용

# 用jq .直接查看json文件内容
# 方式1
jq . kumufengchun.json 
# 方式2
cat kumufengchun.json | jq .


# 输出某个字段或者某个索引的值
# 语法:
jq  '.<key>'  			# 这里key是字段名称
# 实例
jq .name kumufengchun.json
# 输出:"kumufengchun"
# 使用 -r 参数,不含双引号输出结果
jq -r .name kumufengchun.json
# 输出: kumufengchun


# 输出数组的值
# 语法:
jq '.<key>[<value>]' 		# 这里value是数组的索引整数值
# 实例
jq '.company[0]' kumufengchun.json

# 输出列表、数组的一部分,对其进行切片
# 语法:
jq '.<list-key>[s:e]'		# 返回的是数组或者列表的index从s开始(包括s)到e结束(不包括e)
# 实例
jq '.company[0:2]' kumufengchun.json
# 也可以省略开始的index,只有结束的index,如下,仍然是不包括结束index的值
jq '.company[:3]' kumufengchun.json
# 也可以省略结束的index,只有开始的index,如下,输出到最后
jq '.company[1:]' kumufengchun.json
# 开始的索引也可以是负数,表示从后边倒着数,从-1开始数
jq '.company[-2:]' kumufengchun.json


# 循环输出所有的值,如数组嵌套
# 语法:
jq '.[]'
# 实例
jq '.[]' test.json 


# 输出多个索引的值,可以用逗号分割
# 语法:
jq '.key1,.key2'
# 实例
jq '.name,.age' kumufengchun.json
# 如果是数组,用中括号括起来要输出的键值,键值先写谁,先输出谁
jq '.company[2,0]' kumufengchun.json


# 用管道符号|可以对其进行再次处理
# 语法:
jq .[] | .<key1>
# 实例
jq '.[]|.name' test.json


# 括号的作用
echo 1 | jq '(.+2)*5'
# 输出:
15
echo {
    
    1,2,3} | jq '(.+2)*5'
# 输出:
15
20
25

# length求长度,如果是字符串是求的字符串的长度,如果是数组则求得是数组的长度
cat kumufengchun.json | jq '.[] | length'


# 输出所有的keys
# 语法: 
jq keys
# 实例
cat kumufengchun.json | jq 'keys'
# 输出数组的keys(索引)
cat kumufengchun.json | jq '.company | keys'


# 判断存不存在某个键
cat kumufengchun.json | jq 'has("email")'
# 输出:
true

이전 tee 명령의 반환 값을 가져옵니다.

파이프라인에 있는 명령의 경우 use는 $?파이프라인에 있는 마지막 명령의 반환 값만 가져올 수 있습니다.

PIPESTATUS[n], 파이프라인에서 n번째 명령의 반환 값을 가져옵니다.

예:

cp abc def 2>&1 | tee a.log
# ${PIPESTATUS[0]} 获取的是 cp 命令的返回值
test ${
    
    PIPESTATUS[0]} -ne 0 && exit

평가: 문자열 명령 실행

#!/bin/bash
cmd="mkidr aaa"
eval $cmd

문자열 가로채기

var=http://www.aaa.com/123.htm

# 1. # 号截取,删除左边字符,保留右边字符
echo ${var#*//}
  # 其中 var 是变量名,# 号是运算符,*// 表示从左边开始删除第一个 // 号及左边的所有字符
  # 即删除 http://
  # 结果是 :www.aaa.com/123.htm

# 2. ## 号截取,删除左边字符,保留右边字符。
echo ${var##*/}
  # ##*/ 表示从左边开始删除最后(最右边)一个 / 号及左边的所有字符
  # 即删除 http://www.aaa.com/
  # 结果是 123.htm

# 3. %号截取,删除右边字符,保留左边字符
echo ${var%/*}
  # %/* 表示从右边开始,删除第一个 / 号及右边的字符
  # 结果是:http://www.aaa.com
 
# 4. %% 号截取,删除右边字符,保留左边字符
echo ${var%%/*}
  # %%/* 表示从右边开始,删除最后(最左边)一个 / 号及右边的字符
  # 结果是:http:

# 5. 从左边第几个字符开始,及字符的个数
echo ${var:0:5}
  # 其中的 0 表示左边第一个字符开始,5 表示字符的总个数。
  # 结果是:http:

# 6. 从左边第几个字符开始,一直到结束。
echo ${var:7}
  # 其中的 7 表示左边第8个字符开始,一直到结束。
  # 结果是 :www.aaa.com/123.htm
  
# 7. 从右边第几个字符开始,及字符的个数
echo ${var:0-7:3}
  # 其中的 0-7 表示右边算起第七个字符开始,3 表示字符的个数。
  # 结果是:123

# 8. 从右边第几个字符开始,一直到结束
echo ${var:0-7}
  # 表示从右边第七个字符开始,一直到结束。
  # 结果是:123.htm
  
# 注:(左边的第一个字符是用 0 表示,右边的第一个字符用 0-1 表示)

상위 스크립트는 하위 스크립트(하위 프로세스)의 중단을 포착합니다.

  • 종료 0: 프로그램을 정상적으로 실행하고 프로그램을 종료합니다.

  • 종료 1: 비정상 동작으로 프로그램 종료, 종료 후 값이 0보다 크면 모두 비정상 종료

  1. 아래 첨자가 수동으로 중단됨

    #!/bin/bash
    # 子脚本
    echo aaa && exit 1
    
  2. 부모 스크립트는 명령어(tee 명령어가 있을 경우 ${PIPESTATUS[0]}` 사용) 명령어를 통해 $?자식 스크립트의 반환값을 얻는다.


쉘 스크립트는 다른 스크립트를 로드합니다.

#!/bin/bash

# 方式1:source		# 注意:被加载的脚本,不能缺省路径
source ./first.sh

# 方式2:点号(.)		   # 注意:1.被加载的脚本,不能缺省路径。2.点号与脚本文件之间记得要有空格
. ./first.sh
  • 소스 명령을 사용하는 것은 C/C++의 #include 전처리 지시문과 유사한 점(.)과 동일하며 지정된 스크립트 내용을 현재 스크립트로 로드하고 Shell 프로세스에서 실행합니다.
  • sh 명령을 사용하여 다른 스크립트를 호출하면 지정된 스크립트를 실행하기 위해 새 셸 프로세스가 열리고 상위 프로세스의 변수는 하위 프로세스에서 액세스할 수 없습니다.

서브쉘 스레드 활성화

하위 셸은 Linux 스크립트에서 ()를 사용하여 구현됩니다. 즉, ()의 코드는 하위 셸에서 실행됩니다.

추천

출처blog.csdn.net/footless_bird/article/details/123698139