调用存储在变量中的某些命令的正确方法是什么?
1和2之间有什么区别吗?
#!/bin/sh
cmd="ls -la $APPROOTDIR | grep exception"
#1
$cmd
#2
eval "$cmd"
Run Code Online (Sandbox Code Playgroud) 我得到以下变量:
set location "America/New_York"
Run Code Online (Sandbox Code Playgroud)
并希望使用shell语法仅显示/(斜杠)之前的部分.fish
美国
使用bash,我只是使用参数扩展:
location="America/New_York"
echo ${location##*/}"
Run Code Online (Sandbox Code Playgroud)
我怎么做到这一点fish?
我用谷歌搜索并尝试了很多东西,从来没有任何东西可以使用$ {parameter @ operator}.我找到的只是更多链接到相同的文档.因此,我认为通过实际例子得到正确答案对其理解非常有帮助.
文件说:
$ {参数@操作}
扩展可以是参数值的变换,也可以是参数本身的信息,具体取决于运算符的值.每个运营商都是一个字母:
Q
扩展是一个字符串,它是以可以重复用作输入的格式引用的参数值.
它还说引用:
3.1.2引用
引用用于删除shell中某些字符或单词的特殊含义.
所以我的理由是这个(特殊字符$)的输出:
a="To be reused as an input string, \$0 needs to be quoted"
echo ${a@Q}
Run Code Online (Sandbox Code Playgroud)
应该是这个(在""之间,'\'被删除,所以需要再次引用作为输入):
To be reused as an input string, \$0 needs to be quoted
Run Code Online (Sandbox Code Playgroud)
但我得到:
bash: ${a@Q}: bad substitution
Run Code Online (Sandbox Code Playgroud)
我尝试了不同的组合:
${a@q}, "${a@Q}", a='To be reused as an input string, $0 needs to be quoted'
Run Code Online (Sandbox Code Playgroud)
无济于事.
实际上,我尝试使用的任何运算符总是会产生错误的替换错误.这些似乎是bash的非常模糊的特征.我已经从这篇文章中省略了大约半个小时的尝试,每个人都比以前更加扭曲!
我试图在我的PERL5LIB环境变量的末尾附加一个路径,但我不确定这个变量是否总是存在.如果它不存在,我想简单地将它初始化为我试图追加的值.
这是一个有效的例子:
if ( $?PERL5LIB ) then
setenv PERL5LIB ${PERL5LIB}:/some/other/path
else
setenv PERL5LIB /some/other/path
endif
Run Code Online (Sandbox Code Playgroud)
虽然这有效,但它仍然看起来很笨重,因为我必须基本上写两次同一行.我想做的是提出一个更有效的单线解决方案(可能使用参数扩展).
有没有办法将其合并为一条线?(或者多行不涉及多次写出"/ some/other/path")
例如,这可以在bash中完成:
export PERL5LIB=${PERL5LIB:+${PERL5LIB}:}/some/other/path
Run Code Online (Sandbox Code Playgroud) 我最近遇到了这个非常简洁的语法,在创建bash可以接受来自STDIN的参数或流的函数的上下文中(即可以通过管道传递).从表面上看,我理解这里发生了什么,但我想更多地解释一下这是如何工作的实际机制.
这是语法(根据标题): ${1:-$(</dev/stdin)}
在上下文中,可以将其用作:
log(){
echo -e >&1 "INFO: ${1:-$(</dev/stdin)}"
}
Run Code Online (Sandbox Code Playgroud)
允许以下用法:
$ log foo
INFO: foo
Run Code Online (Sandbox Code Playgroud)
或者,您也可以这样做
mv -v foo.ext bar.ext | log
INFO: renamed 'foo.ext' -> 'bar.ext'
Run Code Online (Sandbox Code Playgroud)
这很棒,因为它是我看到的用于启用参数和管道功能的单一最简洁的方法bash(不幸的是我忘记了我现在遇到它的地方).
现在,我理解(或者我认为我理解),这里发生的大部分事情至少表面上看,但我会更加理解.这是我如何解释它,然后是我剩下的问题:
${1:-$(</dev/stdin)}${1} 显然是函数接受的默认参数${1:-x}是否为变量/大括号扩展'后退'到字符串'x',$1否则为空(或未设置?).在这种情况下,回退到STDIN进程子.$()显然是一个</dev/stdin显然是标准输入的重定向,它允许管道工作.这基本上说如果$1不是由参数填充,则回退到使用STDIN - 我在概念上很满意.
所以这是我的问题:
<在$(cat < somefile.ext)).那么当我正在尝试在 bash 脚本中执行一个简单的正则表达式语句,该语句将匹配并替换单词的结尾。下面是我正在尝试做的。
wordh > word:’
Run Code Online (Sandbox Code Playgroud)
下面是我正在使用的代码。
#!/bin/bash
STAT=${STAT/h$/:’}
Run Code Online (Sandbox Code Playgroud)
我不熟悉 bash 脚本,我认为它与 bash 有关系,$因为它用于标记变量。我试图逃避它以及/在它之后添加另一个。当我删除$它时(不检查单词的结尾)。
假设我将一些数据读入 Bash 数组:
$ IFS=" " read -a arr <<< "hello/how are/you iam/fine/yeah"
Run Code Online (Sandbox Code Playgroud)
现在,我想打印/数组中每个元素的第一个切片字段。
我所做的是循环遍历元素并使用 shell 参数扩展从第一个元素中删除所有内容/:
$ for w in "${arr[@]}"; do echo "${w%%/*}"; done
hello
are
iam
Run Code Online (Sandbox Code Playgroud)
但是,sinceprintf允许我们在单个表达式中打印数组的全部内容:
$ printf "%s\n" "${arr[@]}"
hello/how
are/you
iam/fine
Run Code Online (Sandbox Code Playgroud)
...我想知道是否有一种方法可以${w%%/*}在使用时使用 shell 参数扩展printf,而不是循环遍历所有元素并对每个元素执行此操作。
的行为
!(pattern-list)
Run Code Online (Sandbox Code Playgroud)
特别是在参数扩展中使用时,我的工作方式不正常
${parameter/pattern/string}
Run Code Online (Sandbox Code Playgroud)
a="1 2 3 4 5 6 7 8 9 10"
Run Code Online (Sandbox Code Playgroud)
$ printf "%s\n" "${a/!([0-9])/}"
[blank]
#expected 12 3 4 5 6 7 8 9 10
$ printf "%s\n" "${a/!(2)/}"
[blank]
#expected 2 3 4 5 6 7 8 9 10
$ printf "%s\n" "${a/!(*2*)/}"
2 3 4 5 6 7 8 9 10
#Produces the behaviour expected in previous one, not sure why though
$ printf "%s\n" "${a/!(*2*)/,}"
,2 3 4 5 6 …Run Code Online (Sandbox Code Playgroud) 我追求一个纯粹的 bash 解决方案来“slugify”一个变量,这不像我的那么难看。
slugify : 小写,缩短为 63 字节,除 0-9 和 az 之外的所有内容都替换为 -。没有前导/尾随 -。结果是一个适合在 URL 主机名和域名中使用的字符串。输入很可能是一系列带有不想要的字符的单词,例如:
'Effrafax_mUKwT'uP7(Garkbit<\1}@NJ"RJ"Hactar*S;-H%x.?oLazlarl(=Zss@c9?qick.:?BZarquonelW{x>g@'k'
其中一个 slug 看起来像:'effrafax-mukwt-up7-garkbit-1-njrjhactar-shx-olazlarl-zss-c9-q'
slugify () {
next=${1//+([^A-Za-z0-9])/-}
next=${next:0:63}
next=${next,,}
next=${next#-}
next=${next%-}
echo $next
}
Run Code Online (Sandbox Code Playgroud)
另外为什么不${next//^-|-$}去掉前缀和后缀'-'?其他建议?
我正在尝试将一些代码从 bash 5.1 移植到 4.2.46。一个尝试从特定格式的字符串中去除颜色代码的函数停止工作。
text这是这种格式的示例字符串。我为此打开了扩展通配符。
text="$(printf -- "%b%s%b" "\[\e[31m\]" "hello" "\[\e[0m\]")"
shopt -s extglob
Run Code Online (Sandbox Code Playgroud)
在 bash 5.1 中,此参数扩展可删除所有颜色代码和转义字符
bash-5.1$ echo "${text//$'\[\e'\[/}"
31m\]hello0m\]
bash-5.1$ echo "${text//$'\[\e'\[+([0-9])/}"
m\]hellom\]
bash-5.1$ echo "${text//$'\[\e'\[+([0-9])m$'\]'/}"
hello
Run Code Online (Sandbox Code Playgroud)
在 bash 4.2.46 中,当我构建参数扩展时,我开始出现不同的行为。
bash-4.2.46$ echo "${text//$'\[\e'\[/}"
\31m\]hello\0m\]
bash-4.2.46$ echo "${text//$'\[\e'\[+([0-9])/}"
\[\]hello\[\] ## no longer matches because `+([0-9])` doesn't follow `\[`
Run Code Online (Sandbox Code Playgroud)
差异来自于这一行:echo "${text//$'\[\e'\[/}"
bash-5.1: 31m\]hello0m\]
bash-4.2.46: \31m\]hello\0m\]
Run Code Online (Sandbox Code Playgroud)
显示内容如下printf "%q" "${text//$'\[\e'\[/}":
bash-5.1: 31m\\\]hello0m\\\]
bash-4.2.46: \\31m\\\]hello\\0m\\\]
Run Code Online (Sandbox Code Playgroud)
4.2.26 中的额外内容从哪里来\?
即使当我尝试删除它时,模式也会停止匹配:
bash-5.1: 31m\]hello0m\]
bash-4.2.46: \31m\]hello\0m\]
Run Code Online (Sandbox Code Playgroud)
我猜测可能存在与参数扩展、反斜杠转义和扩展通配符相关的错误。
我的目标是编写适用于 …