bash引用-Quoting详细介绍

bash引用-Quoting详细介绍

概述

  • 引用的字面意思就是,用引号括住一个字符串。这可以保护字符串中的特殊字符不被shell或shell脚本重新解释或扩展。(如果一个字有不同于其字面意思的解释,它就是“特殊的”。例如:星号*除了本身代表*号以外还表示文件通配和正则表达式中的通配符)。
[root@centos8 ~]$ ls -l P*
Pictures:
total 0
Public:
total 0
[root@centos8 ~]$ ls -l 'P*'
ls: cannot access 'P*': No such file or directory
  • 在生活中用语或者书写,当我们使用双引号"引用"一个句子时,我们会区别对待该句子并赋予其特殊意义;在Bash脚本中,当我们使用双引号"string"引用一个字符串时,我们同样区别对待并保护其字面意思(一般性的意思)。

  • 在涉及到命令替换时,引用可以让echo输出带格式的命令结果,保留变量所带的空白符号。

bash$ echo $(ls -l)                 # 无引号命令替换
total 8 -rw-rw-r-- 1 bo bo 13 Aug 21 12:57 t.sh -rw-rw-r-- 1 bo bo 78 Aug 21 12:57 u.sh
bash$ echo "$(ls -l)"               # 被引用的命令替换
total 8-rw-rw-r--  1 bo bo  13 Aug 21 12:57 t.sh-rw-rw-r--  1 bo bo  78 Aug 21 12:57 u.sh

5.1. 引用变量(Quoting Variables)

  • 当我们引用一个变量时,比较建议的做法是使用双引号将其引用起来。这样做可以避免bash再次解析双引号中的特殊字符(只不过:$、反引号`、和反斜杠\仍然会被bash解析)。在双引号中的$符号仍然被视为特殊字符,这样做的好处是可以进行变量替换(“$variable”),也就是使用变量的值替换掉变量名。

  • 使用双引号的另一个用途是防止单词分割。在双引号中的参数表现为单个词语(即使其包含空白字符)。

List="one two three"
for a in $List     # 使用空格符作为分隔符分割变量的值(字符串).
doecho "$a"
done
# 输出
# one
# two
# three
echo "---"
for a in "$List"   # Preserves whitespace in a single variable.
do #     ^     ^echo "$a"
done
# 输出
# one two three
  • 下面是一个更加精心设计的例子
variable1="a variable containing five words"
COMMAND This is $variable1    # 执行COMMAND命令时会被认为带了7个参数如下:
# "This" "is" "a" "variable" "containing" "five" "words"
COMMAND "This is $variable1"  # # 执行COMMAND命令时会被认为带了1个参数如下:
# "This is a variable containing five words"
variable2=""    # 空变量.
COMMAND $variable2 $variable2 $variable2# COMMAND命令没带参数执行. 
COMMAND "$variable2" "$variable2" "$variable2"# 带了三个空参数执行COMMAND命令. 
COMMAND "$variable2 $variable2 $variable2"# COMMAND命令带一个参数执行(该参数为2个空格). 
# 谢谢这个大佬指出:Stéphane Chazelas.
  • 使用echo给标准输出打印奇怪的字符

例 5-1. echo输出奇怪的变量

#!/bin/bash
# weirdvars.sh: Echoing weird variables.
echo
var="'(]\\{}\$\""
echo $var        # '(]\{}$"
echo "$var"      # '(]\{}$"     结果相同.
echo
IFS='\'
echo $var        # '(] {}$"     \ 变为了空格,为什么?(IFS为内部域分割符,临时使用'\'作为分隔符)
echo "$var"      # '(]\{}$"
# 以上例子来自Stephane Chazelas.
echo
var2="\\\\\""
echo $var2       #   "
echo "$var2"     # \\"
echo
# 但是 ... var2="\\\\"" 是非法的?(此处四个\,位置2,4的两个刚好被转义,而剩余3个"符,所以不行)
var3='\\\\'
echo "$var3"     # \\\\
# 但是强引用可以.
# ************************************************************ #
# 变量嵌套替换也可以
echo "$(echo '"')"           # "
#    ^           ^
# 某些情况下嵌套很有用
var1="Two bits"
echo "\$var1 = "$var1""      # $var1 = Two bits
#    ^                ^
# Or, as Chris Hiestand points out ...
if [[ "$(du "$My_File1")" -gt "$(du "$My_File2")" ]]
#     ^     ^         ^ ^     ^     ^         ^ ^
then...
fi
# ************************************************************ #
  • 单引号(’ ')的工作机制类似于双引号,但是在单括号中不允许变量替换,因为$符的特殊意义被关闭了。在单引号中任何特殊的符号都按照字面意思解释(除了’单引号自身)。

  • 由于转义符(逃逸符)在单引号中都失去了转义的意义,所以试图在单引号中括单引号是不行的,下面的例子可以实现输出单引号。

echo "Why can't I write 's between single quotes"
echo
# The roundabout method.
echo 'Why can'\''t I write '"'"'s between single quotes'
#    |-------|  |----------|   |-----------------------|
# 上面使用了三个单引号组;一个转义的单引号和一个双引号引起的单引号.

5.2. 转义/逃逸(Escaping)

  • 转义是一种用来引用单个字符的方法。在字符前的反斜杠\告诉shell以字面意思解析该字符。

注意:在echo或者sed这些程序命令中,转义某个字符可能有相反的作用,可以触发某种特殊意义。

特定的被转义的字符所具有的意义如下:

used with echo and sed
\n 新行(means newline)
\r 回车(means return)
\t tab键
\v 垂直tab键(means vertical tab)
\b 退格(means backspace)
\a 报警(means alert (beep or flash))
\0xx 将反斜杠后的数字视为八进制的ASCII码值
  • $’ … ’ :该符号结构的机制是使用转义的八进制或者十六进制值将ASCII码赋给变量;例如:quote=$‘\042’.

例5-2. 被转义的字符(Escaped Characters)

#!/bin/bash
# escaped.sh: escaped characters
#############################################################
### First, let's show some basic escaped-character usage. ###
#############################################################
# Escaping a newline.
# ------------------
echo ""
echo "This will print
as two lines."
# 上面的写法将会打印两行
echo "This will print \
as one line."
# 上面的写法将会打印一行
echo; echo
echo "============="
echo "\v\v\v\v"      # 按照字面意思打印 \v\v\v\v .
# 使用 -e 选项 打印转义字符所代表的字符
echo "============="
echo "VERTICAL TABS" # 垂直tab键
echo -e "\v\v\v\v"   # 此时将会打印四个垂直tab
echo "=============="
echo "QUOTATION MARK"
echo -e "\042"       # 打印一个双引号 " (quote, 八进制的 ASCII 值:42;代表一个双引号).
echo "=============="
# 使用该结构 $'\X' 使得-e选项不在需要
echo; echo "NEWLINE and (maybe) BEEP"
echo $'\n'           # 新行.
echo $'\a'           # 警告音(beep).# May only flash, not beep, depending on terminal.
# We have seen $'\nnn" string expansion, and now . . .
# =================================================================== #
# $'\nnn' 该种字符串展开的机制在bash2.0中引进
# =================================================================== #
echo "Introducing the \$\' ... \' string-expansion construct . . . "
echo ". . . featuring more quotation marks."
echo $'\t \042 \t'   # 打印左右两边分别有个tab键的双引号(").
# '\nnn' 为八进制数.
echo
# 将一个ASCII字符赋值给一个变量
# ----------------------------------------
quote=$'\042'        # " 赋值给一个变量
echo "$quote Quoted string $quote and this lies outside the quotes."
echo
# Concatenating ASCII chars in a variable.
triple_underline=$'\137\137\137'  # 137 是八进制的ASCII值,代表'_'.
echo "$triple_underline UNDERLINE $triple_underline"
echo
ABC=$'\101\102\103\010'           # 101, 102, 103 分别代表 A, B, C.
echo $ABC
echo
escape=$'\033'                    # 033 是escape的八进制表示.
echo "\"escape\" echoes as $escape"
#                                   并无可视化的输出.
echo
exit 0
  • 一个更加精心设计的例子

例5-3. 检测按键(Detecting key-presses)

#!/bin/bash
# Author: Sigurd Solaas, 20 Apr 2011
# Used in ABS Guide with permission.
# Requires version 4.2+ of Bash.
key="no value yet"
while true; doclearecho "Bash Extra Keys Demo. Keys to try:"#Bash 识别按键的demo.可以识别一下按键:echoecho "* Insert, Delete, Home, End, Page_Up and Page_Down"echo "* The four arrow keys"#四个方向键echo "* Tab, enter, escape, and space key"#tab,回车,返回,空格键echo "* The letter and number keys, etc."#标点按键echoecho "    d = show date/time"echo "    q = quit"echo "================================"echo# Convert the separate home-key to home-key_num_7:if [ "$key" = $'\x1b\x4f\x48' ]; thenkey=$'\x1b\x5b\x31\x7e'#   Quoted string-expansion construct. fi# Convert the separate end-key to end-key_num_1.if [ "$key" = $'\x1b\x4f\x46' ]; thenkey=$'\x1b\x5b\x34\x7e'ficase "$key" in$'\x1b\x5b\x32\x7e')  # Insertecho Insert Key;;$'\x1b\x5b\x33\x7e')  # Deleteecho Delete Key;;$'\x1b\x5b\x31\x7e')  # Home_key_num_7echo Home Key;;$'\x1b\x5b\x34\x7e')  # End_key_num_1echo End Key;;$'\x1b\x5b\x35\x7e')  # Page_Upecho Page_Up;;$'\x1b\x5b\x36\x7e')  # Page_Downecho Page_Down;;$'\x1b\x5b\x41')  # Up_arrowecho Up arrow;;$'\x1b\x5b\x42')  # Down_arrowecho Down arrow;;$'\x1b\x5b\x43')  # Right_arrowecho Right arrow;;$'\x1b\x5b\x44')  # Left_arrowecho Left arrow;;$'\x09')  # Tabecho Tab Key;;$'\x0a')  # Enterecho Enter Key;;$'\x1b')  # Escapeecho Escape Key;;$'\x20')  # Spaceecho Space Key;;d)date;;q)echo Time to quit...echoexit 0;;*)echo You pressed: \'"$key"\';;esacechoecho "================================"unset K1 K2 K3read -s -N1 -p "Press a key: "K1="$REPLY"read -s -N2 -t 0.001K2="$REPLY"read -s -N1 -t 0.001K3="$REPLY"key="$K1$K2$K3"
done
exit $?

\" 还原双引号的字面意思(就是双引号,不在用于引用)

echo "Hello"                     # Hello
echo "\"Hello\" ... he said."    # "Hello" ... he said.

$ 还原$符的字面意思,意思是在$后的变量不会被替换

echo "\$variable01"           # $variable01
echo "The book cost \$7.98."  # The book cost $7.98.

\\ 还原\的字面意思

echo "\\"  # Results in \
# Whereas . . .
echo "\"   # Invokes secondary prompt from the command-line.# In a script, gives an error message.
# However . . .
echo '\'   # Results in \
  • 反斜杠\在不同的情况下表现出不一样的行为(是否被转义;是否位于强引用中;是否在弱引用中;是否在命令替换中;是否在“here document”)
                      #  简单的转义和引用
echo \z               #  z
echo \\z              # \z
echo '\z'             # \z
echo '\\z'            # \\z
echo "\z"             # \z
echo "\\z"            # \z#  命令替换
echo ècho \z`        #  z
echo ècho \\z`       #  z
echo ècho \\\z`      # \z
echo ècho \\\\z`     # \z
echo ècho \\\\\\z`   # \z
echo ècho \\\\\\\z`  # \\z
echo ècho "\z"`      # \z
echo ècho "\\z"`     # \z# 此处文本(Here document)
cat <<EOF              
\z                      
EOF                   # \z
cat <<EOF              
\\z                     
EOF                   # \z
# These examples supplied by Stéphane Chazelas.
  • 赋给某个变量的字符串中的某些元素可能会被(能够被)转义,但是单个被转义的字符不一定可以赋给变量。
variable=\
echo "$variable"
# 不可行,打印一个错误提示:
# test.sh: : command not found
# 单独一个转义字符不可赋给变量
#
#  事实上此处转义字符 "\" 转义了新行(在编写比较长的命令时就可以使用一个转义符来将命令写成多行)
#+ 真正的行为是:        variable=echo "$variable"
#+                      把命令赋值给变量是不允许的
variable=\
23skidoo
echo "$variable"        #  23skidoo#  可行,因为第二行是合法的变量,且实际上第二行被转义成了第一。
variable=\ 
#        \^    转义符后跟一个空格 
echo "$variable"        # 输出空格
variable=\\
echo "$variable"        # \
variable=\\\
echo "$variable"
# 行不通,出错:
# test.sh: \: command not found
#
#  上面三个转义符中,第一个转义可第二个,但是第三个转义符还在,类似于第一个例子。
variable=\\\\
echo "$variable"        # \\# Second and fourth escapes escaped.# This is o.k.
  • 转义空格可以防止命令的参数列表发生词语分割。
  • Escaping a space can prevent word splitting in a command’s argument list.
file_list="/bin/cat /bin/gzip /bin/more /usr/bin/less /usr/bin/emacs-20.7"
# List of files as argument(s) to a command.# Add two files to the list, and list all.
ls -l /usr/X11R6/bin/xsetroot /sbin/dump $file_list
echo "-------------------------------------------------------------------------"
# What happens if we escape a couple of spaces?
ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list
输出:
################################
[root@centos8 ~]#ls -l /usr/X11R6/bin/xsetroot\ /sbin/dump\ $file_list
ls: cannot access '/usr/X11R6/bin/xsetroot /sbin/dump /bin/cat': No such file or directory
################################
# Error: the first three files concatenated into a single argument to 'ls -l'
#        because the two escaped spaces prevent argument (word) splitting.
  • 转义也有"等待多行命令"的意思。一般的,不同的行会是不同的命令,但是行末的转义字符转义了新行的字符,命令可以一直写到下一行。
(cd /source/directory && tar cf - . ) | \
(cd /dest/directory && tar xpvf -)
# 该命令为Alan Cox写的拷贝命令,作两行写,增加了易读性。
# 下面的命令同样功能:
tar cf - -C /source/directory . |
tar xpvf - -C /dest/directory
# See note below.
# (Thanks, Stéphane Chazelas.)
  • 如果脚本行结束跟一个|,一个管道符号,那么转义字符\,就不是那么严格的需要了。但是后面跟上转义字符是比较好的习惯。
echo "foo
bar" 
##两行
#foo
#bar
echo
echo 'foo
bar'    # 仍然是两行
#foo
#bar
echo
echo foo\
bar     # 换行符被转义输出一行.
#foobar
echo
echo "foo\
bar"     # 同样是一行,转义字符在弱引用中("\")不会丢掉其转义字符的特殊意义。
#foobar
echo
echo 'foo\
bar'     # 两行,因为转义字符在强引用('\')中失去了转义字符的意义,被bash按照字面意义解释。
#foo\
#bar
# Examples suggested by Stéphane Chazelas.

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/22449.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

dflow工作流使用1——架构和基本概念

对于容器技术、工作流等概念完全不懂的情况下理解dflow的工作方式会很吃力&#xff0c;这里记录一下个人理解。 dflow涉及的基本概念 工作流的概念很好理解&#xff0c;即某个项目可以分为多个步骤&#xff0c;每个步骤可以实现独立运行&#xff0c;只保留输入输出接口&#x…

【方法】Excel表格如何拆分数据?

当需要把多个数据逐个填到Excel单元格的时候&#xff0c;我们可以利用Excel的数据拆分功能&#xff0c;可以节省不少时间。 小编以下面的数据为例&#xff0c;看看如何进行数据拆分。 首先&#xff0c;要选择数字所在的单元格&#xff0c;然后依次点击菜单栏中的“数据”>…

Spring中的事务

一、为什么需要事务&#xff1f; 事务定义 将一组操作封装成一个执行单元&#xff08;封装到一起&#xff09;&#xff0c;要么全部成功&#xff0c;要么全部失败。 为什么要用事务&#xff1f; 比如转账分为两个操作&#xff1a; 第一步操作&#xff1a; A 账户 -100 元…

[Pytorch]手写数字识别——真·手写!

Github网址&#xff1a;https://github.com/diaoquesang/pytorchTutorials/tree/main 本教程创建于2023/7/31&#xff0c;几乎所有代码都有对应的注释&#xff0c;帮助初学者理解dataset、dataloader、transform的封装&#xff0c;初步体验调参的过程&#xff0c;初步掌握openc…

jsqlparser 安装和使用

jsqlparser是sql语句解析工具&#xff0c;可以解析sql并分析语法。 安装 <dependency><groupId>com.github.jsqlparser</groupId><artifactId>jsqlparser</artifactId><version>4.3</version> </dependency>使用 String s …

【语音合成】微软 edge-tts

目录 1. edge-tts 介绍 2. 代码示例 1. edge-tts 介绍 https://github.com/rany2/edge-tts 在Python代码中使用Microsoft Edge的在线文本到语音服务 2. 代码示例 import asyncio # pip install edge_tts import edge_tts TEXT """给我放首我喜欢听的歌曲…

React ~ React Router 6

React Router 6 VS React Router 5.x 内置组件的变化; 移除<Switch /> , 新增<Routes />语法的变化; component { About } 变为 element { <About /> }新增多个hook官方明确推荐函数式组件了! 一级路由(变化) 安装路由 npm i react-router-dom (默认是最…

【数据结构】快速排序

快速排序是一种高效的排序算法&#xff0c;其基本思想是分治法。它将一个大问题分解成若干个小问题进行解决&#xff0c;最后将这些解合并得到最终结果。 快速排序的主要思路如下&#xff1a; 选择一个基准元素&#xff1a;从待排序的数组中选择一个元素作为基准&#xff08;…

Spring指定bean在哪个应用加载

1.背景 某项目,spring架构,有2个不同的WebAppApplication入口,大部分service类共用,小部分类有区别,只需要在一个应用中加载,不需要在另一个应用中加载. 2.实现代码 自定义限制注解 package mis.shared.annotation;import java.lang.annotation.ElementType; import java.lan…

springboot+maven插件调用mybatis generator自动生成对应的mybatis.xml文件和java类

mybatis最繁琐的事就是sql语句和实体类&#xff0c;sql语句写在java文件里很难看&#xff0c;字段多的表一开始写感觉阻力很大&#xff0c;没有耐心&#xff0c;自动生成便成了最称心的做法。自动生成xml文件&#xff0c;dao接口&#xff0c;实体类&#xff0c;虽一直感觉不太优…

skywalking全链路追踪

文章目录 一、介绍二、全链路追踪1. 测试1 - 正常请求2. 测试2 - 异常请求 三、过滤非业务请求链路1. 链路忽略插件2. 配置3. 测试 一、介绍 在上一篇文章skywalking安装教程中我们介绍了skywalking的作用以及如何将其集成到我们的微服务项目中。本篇文章我们介绍在微服务架构…

没有jodatime,rust怎么方便高效的操作时间呢?

关注我&#xff0c;学习Rust不迷路&#xff01;&#xff01; 当使用Rust进行日期操作时&#xff0c;可以使用 chrono 库。下面给出了二十个常见的日期操作的例子&#xff1a; 1. 获取当前日期和时间&#xff1a; use chrono::prelude::*;let current_datetime Local::now()…

router 跳转打开新窗口

let url router.resolve({name: screen, })?.hrefwindow.open(url, _black)注意&#xff1a;新窗口无法全屏 参考链接&#xff1a;https://stackoverflow.com/questions/29281986/run-a-website-in-fullscreen-mode/30970886#30970886

数据库索引失效的情况

1.对添加了索引的字段进行函数运算 2.如果是字符串类型的字段&#xff0c;如果不加单引号也会导致索引失效 3.如果最索引字段使用模糊查询&#xff0c;如果是头部模糊索引将失效&#xff0c;如果是尾部模糊索引则正常 4.如果使用or分割符&#xff0c;如果or前面的条件中的列有…

nano命令

nano 被编辑的文件.txt等 输入xxxx crtl键X 输入yes 按enter保存 使用nano命令编辑文件或创建新文件&#xff0c;可按以下快捷键&#xff1a; 用法 光标控制 移动光标&#xff1a;使用用方向键移动。 选择文字&#xff1a;按住鼠标左键拖到。 复制、剪贴和粘贴 复制一整行&…

基于Yolov2深度学习网络的车辆检测算法matlab仿真

目录 1.算法运行效果图预览 2.算法运行软件版本 3.部分核心程序 4.算法理论概述 4.1. 卷积神经网络&#xff08;CNN&#xff09; 4.2. YOLOv2 网络 4.3. 实现过程 4.4. 应用领域 5.算法完整程序工程 1.算法运行效果图预览 2.算法运行软件版本 MATLAB2022A 3.部分核心…

使用css和js给按钮添加微交互的几种方式

使用css和js给按钮添加微交互的几种方式 在现实世界中&#xff0c;当我们轻弹或按下某些东西时&#xff0c;它们会发出咔嗒声&#xff0c;例如电灯开关。有些东西会亮起或发出蜂鸣声&#xff0c;这些响应都是“微交互”&#xff0c;让我们知道我们何时成功完成了某件事。在本文…

【Winform学习笔记(五)】引用自定义控件库(dll文件)

引用自定义控件库dll文件 前言正文1、生成dll文件2、选择工具箱项3、选择需要导入的dll文件4、确定需要导入的控件5、导入及使用 前言 在本文中主要介绍 如何引用自定义控件库(dll文件)。 正文 1、生成dll文件 通过生成解决方案 或 重新生成解决方案 生成 dll 文件 生成的…

小程序页面传递布尔值不起作用的解决方法

问题 传参&#xff1a; wx.navigateTo({url: ../mymeet/mymeeting-detail?isprincipaltrue, })以下方式使用时不起作用或出现问题&#xff1a; onLoad(options) {if (options.isprincipal) {...}//或者if (options.isprincipal true) {...} }原因 这种方式传参后isprinci…

如何发布自己的npm包

发布一个简单的npm包 首先创建一个文件夹&#xff08;唯一的命名&#xff09;创建package.json包&#xff0c;输出npm init&#xff0c;一直回车就好。创建index.js文件&#xff0c;向外暴露方法。 将包上传或更新到 npm 执行登录命令&#xff1a;npm login 登录npm官网&…