Joh*_*ohn 1513 bash shell command-line
我有一个非常简单的脚本,如下所示:
#!/bin/bash
VAR1="$1"
MOREF='sudo run command against $VAR1 | grep name | cut -c7-'
echo $MOREF
Run Code Online (Sandbox Code Playgroud)
当我从命令行运行此脚本并将参数传递给它时,我没有得到任何输出.但是,当我运行$MOREF
变量中包含的命令时,我能够获得输出.
我想知道如何获取需要在脚本中运行的命令的结果,将其保存到变量,然后在屏幕上输出该变量?
And*_*ter 2211
除了反引号(`command`
),你可以使用$(command)
,我觉得更容易阅读,并允许嵌套.
OUTPUT="$(ls -1)"
echo "${OUTPUT}"
MULTILINE=$(ls \
-1)
echo "${MULTILINE}"
Run Code Online (Sandbox Code Playgroud)
Quoting("$(command)"
)对保留多行值很重要.
Ily*_*gan 265
更新(2018年):正确的方法是
$(sudo run command)
Run Code Online (Sandbox Code Playgroud)
你使用的是错误的撇号.你需要`
,没有'
.这个角色被称为"反叛"(或"重音").
像这样:
#!/bin/bash
VAR1="$1"
VAR2="$2"
MOREF=`sudo run command against "$VAR1" | grep name | cut -c7-`
echo "$MOREF"
Run Code Online (Sandbox Code Playgroud)
小智 72
正如他们已经向你指出的那样,你应该使用'反引号'.
提出的替代方案$(command)
也有效,并且它也更容易阅读,但请注意它仅对bash或korn shell(以及从这些shell派生的shell)有效,因此如果您的脚本必须在各种Unix系统上真正可移植,那么您应该更喜欢旧的反引号符号.
F. *_*uri 66
第二次编辑2018-02-12:添加一种不同的方式,在此底部搜索长时间运行的任务!
2018-01-25编辑:添加示例函数(用于填充有关磁盘使用情况的变量)
myPi=`echo '4*a(1)' | bc -l`
echo $myPi
3.14159265358979323844
Run Code Online (Sandbox Code Playgroud)
由于嵌套可能变得很重,因此为此实现了括号
myPi=$(bc -l <<<'4*a(1)')
Run Code Online (Sandbox Code Playgroud)
嵌套样本:
SysStarted=$(date -d "$(ps ho lstart 1)" +%s)
echo $SysStarted
1480656334
Run Code Online (Sandbox Code Playgroud)
df -k /
Filesystem 1K-blocks Used Available Use% Mounted on
/dev/dm-0 999320 529020 401488 57% /
Run Code Online (Sandbox Code Playgroud)
如果我只想要使用值:
array=($(df -k /))
Run Code Online (Sandbox Code Playgroud)
你可以看到数组变量:
declare -p array
declare -a array='([0]="Filesystem" [1]="1K-blocks" [2]="Used" [3]="Available" [
4]="Use%" [5]="Mounted" [6]="on" [7]="/dev/dm-0" [8]="999320" [9]="529020" [10]=
"401488" [11]="57%" [12]="/")'
Run Code Online (Sandbox Code Playgroud)
然后:
echo ${array[9]}
529020
Run Code Online (Sandbox Code Playgroud)
但我更喜欢这个:
{ read foo ; Read filesystem size using avail prct mountpoint ; } < <(df -k /)
echo $used
529020
Run Code Online (Sandbox Code Playgroud)
1st read foo
将只跳过标题行(变量$foo
将包含类似的东西Filesystem 1K-blocks Used Available Use% Mounted on
)
#!/bin/bash
declare free=0 total=0 used=0
getDiskStat() {
local foo
{
read foo
read foo total used free foo
} < <(
df -k ${1:-/}
)
}
getDiskStat $1
echo $total $used $free
Run Code Online (Sandbox Code Playgroud)
Nota:declare
行不是必需的,只是为了便于阅读.
sudo cmd | grep ... | cut ...
shell=$(cat /etc/passwd | grep $USER | cut -d : -f 7)
echo $shell
/bin/bash
Run Code Online (Sandbox Code Playgroud)
(请避免无用cat
!所以这只是1叉少:
shell=$(grep $USER </etc/passwd | cut -d : -f 7)
Run Code Online (Sandbox Code Playgroud)
所有管道(|
)都表示叉子.必须运行另一个进程,访问磁盘,库调用等.
所以使用sed
for sample,会将subprocess限制为只有一个fork:
shell=$(sed </etc/passwd "s/^$USER:.*://p;d")
echo $shell
Run Code Online (Sandbox Code Playgroud)
但对于许多操作,主要是小文件,bash可以自己完成这项工作:
while IFS=: read -a line ; do
[ "$line" = "$USER" ] && shell=${line[6]}
done </etc/passwd
echo $shell
/bin/bash
Run Code Online (Sandbox Code Playgroud)
要么
while IFS=: read loginname encpass uid gid fullname home shell;do
[ "$loginname" = "$USER" ] && break
done </etc/passwd
echo $shell $loginname ...
Run Code Online (Sandbox Code Playgroud)
看看我如何在Bash中的分隔符上拆分字符串的答案?
第2编辑2018-02-12: 为了防止像多个叉子一样
myPi=$(bc -l <<<'4*a(1)'
myRay=12
myCirc=$(bc -l <<<" 2 * $myPi * $myRay ")
Run Code Online (Sandbox Code Playgroud)
要么
myStarted=$(date -d "$(ps ho lstart 1)" +%s)
mySessStart=$(date -d "$(ps ho lstart $$)" +%s)
Run Code Online (Sandbox Code Playgroud)
这工作正常,但运行许多叉子是沉重和缓慢.
和命令,date
并且bc
可以一行一行地进行许多操作!
看到:
bc -l <<<$'3*4\n5*6'
12
30
date -f - +%s < <(ps ho lstart 1 $$)
1516030449
1517853288
Run Code Online (Sandbox Code Playgroud)
因此,我们可以使用长时间运行的后台进程来创建许多作业,而无需为每个请求启动新的fork.
我们只需要一些文件描述符和fifos来正确执行此操作:
mkfifo /tmp/myFifoForBc
exec 5> >(bc -l >/tmp/myFifoForBc)
exec 6</tmp/myFifoForBc
rm /tmp/myFifoForBc
Run Code Online (Sandbox Code Playgroud)
(当然,FD 5
并且6
必须不使用!)......从那里,您可以通过以下方式使用此过程:
echo "3*4" >&5
read -u 6 foo
echo $foo
12
echo >&5 "pi=4*a(1)"
echo >&5 "2*pi*12"
read -u 6 foo
echo $foo
75.39822368615503772256
Run Code Online (Sandbox Code Playgroud)
newConnector
您可以newConnector
在GitHub.Com或我自己的网站上找到我的功能(在github上的Nota ,我的网站上有两个文件,功能和演示被捆绑到一个文件中,可以使用或只运行演示)
样品:
. shell_connector.sh
tty
/dev/pts/20
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30745 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
newConnector /usr/bin/bc "-l" '3*4' 12
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
30952 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
declare -p PI
bash: declare: PI: not found
myBc '4*a(1)' PI
declare -p PI
declare -- PI="3.14159265358979323844"
Run Code Online (Sandbox Code Playgroud)
该函数myBc
允许您使用简单语法的后台任务,并使用日期:
newConnector /bin/date '-f - +%s' @0 0
myDate '2000-01-01'
946681200
myDate "$(ps ho lstart 1)" boottime
myDate now now ; read utm idl </proc/uptime
myBc "$now-$boottime" uptime
printf "%s\n" ${utm%%.*} $uptime
42134906
42134906
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
29019 pts/20 Ss 0:00 bash
30944 pts/20 S 0:00 \_ /usr/bin/bc -l
32615 pts/20 S 0:00 \_ /bin/date -f - +%s
3162 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
Run Code Online (Sandbox Code Playgroud)
从那里,如果你想结束一个后台进程,你只需要关闭他的fd:
eval "exec $DATEOUT>&-"
eval "exec $DATEIN>&-"
ps --tty pts/20 fw
PID TTY STAT TIME COMMAND
4936 pts/20 Ss 0:00 bash
5256 pts/20 S 0:00 \_ /usr/bin/bc -l
6358 pts/20 R+ 0:00 \_ ps --tty pts/20 fw
Run Code Online (Sandbox Code Playgroud)
这是不需要的,因为当主要过程结束时所有fd都关闭.
MLS*_*LSC 53
我知道三种方法:
1)功能适用于此类任务:
func (){
ls -l
}
Run Code Online (Sandbox Code Playgroud)
通过说出来调用它 func
2)另一个合适的解决方案可能是eval:
var="ls -l"
eval $var
Run Code Online (Sandbox Code Playgroud)
3)第三个是直接使用变量:
var=$(ls -l)
OR
var=`ls -l`
Run Code Online (Sandbox Code Playgroud)
你可以很好地得到第三种解决方案的输出:
echo "$var"
Run Code Online (Sandbox Code Playgroud)
还有令人讨厌的方式:
echo $var
Run Code Online (Sandbox Code Playgroud)
Dig*_*oss 27
只是为了与众不同:
MOREF=$(sudo run command against $VAR1 | grep name | cut -c7-)
Run Code Online (Sandbox Code Playgroud)
Emi*_*mil 18
设置变量时,请确保在=符号之前和/或之后没有空格.花了一个小时试图弄清楚这一点,尝试各种解决方案!这不酷.
正确:
WTFF=`echo "stuff"`
echo "Example: $WTFF"
Run Code Online (Sandbox Code Playgroud)
将失败并出现错误:(东西:未找到或类似)
WTFF= `echo "stuff"`
echo "Example: $WTFF"
Run Code Online (Sandbox Code Playgroud)
Jah*_*hid 14
如果你想用multiline/multiple命令执行它,那么你可以这样做:
output=$( bash <<EOF
# Multiline/multiple command/s
EOF
)
Run Code Online (Sandbox Code Playgroud)
要么:
output=$(
# Multiline/multiple command/s
)
Run Code Online (Sandbox Code Playgroud)
例:
#!/bin/bash
output="$( bash <<EOF
echo first
echo second
echo third
EOF
)"
echo "$output"
Run Code Online (Sandbox Code Playgroud)
输出:
first
second
third
Run Code Online (Sandbox Code Playgroud)
使用heredoc,您可以通过将长单行代码分解为多行代码来轻松简化操作.另一个例子:
output="$( ssh -p $port $user@$domain <<EOF
# Breakdown your long ssh command into multiline here.
EOF
)"
Run Code Online (Sandbox Code Playgroud)
你需要使用其中之一
$(command-here)
要么
`command-here`
Run Code Online (Sandbox Code Playgroud)
例
#!/bin/bash
VAR1="$1"
VAR2="$2"
MOREF="$(sudo run command against "$VAR1" | grep name | cut -c7-)"
echo "$MOREF"
Run Code Online (Sandbox Code Playgroud)
如今,Mac/OSX 带有旧的 Bash 版本,即GNU bash, version 3.2.57(1)-release (arm64-apple-darwin21)
. 在这种情况下,可以使用:
new_variable="$(some_command)"
Run Code Online (Sandbox Code Playgroud)
一个具体的例子:
newvar="$(echo $var | tr -d '123')"
Run Code Online (Sandbox Code Playgroud)
请注意()
, ,而不是{}
Bash 4 中常见的符号。
这是另一种方式,适用于某些文本编辑器,这些编辑器无法正确突出显示您创建的每个复杂代码.
read -r -d '' str < <(cat somefile.txt)
echo "${#str}"
echo "$str"
Run Code Online (Sandbox Code Playgroud)
你可以使用反蜱(也称为重点坟墓)或$()
.像 - 作为 -
OUTPUT=$(x+2);
OUTPUT=`x+2`;
Run Code Online (Sandbox Code Playgroud)
两者都有相同的效果.但OUTPUT = $(x + 2)更易读,也是最新的.
如果您尝试执行的命令失败,它会将输出写入错误流,然后打印到控制台。
为了避免它,您必须重定向错误流:
result=$(ls -l something_that_does_not_exist 2>&1)
Run Code Online (Sandbox Code Playgroud)
小智 5
这里还有两种方法:
请记住,空间在 Bash 中非常重要。因此,如果您希望命令运行,请按原样使用,而无需引入更多空格。
下面赋值harshil
给L
然后打印出来
L=$"harshil"
echo "$L"
Run Code Online (Sandbox Code Playgroud)下面将命令的输出分配tr
给 L2。tr
正在对另一个变量 L1 进行操作。
L2=$(echo "$L1" | tr [:upper:] [:lower:])
Run Code Online (Sandbox Code Playgroud) 归档时间: |
|
查看次数: |
1703001 次 |
最近记录: |