我在Linux下和solaris下运行相同的脚本.这是脚本:
#!/bin/sh
index=0
ls /tmp | grep e |
while read fileWithE
do
echo $fileWithE
index=`expr $index + 1`
done
echo "index is $index"
Run Code Online (Sandbox Code Playgroud)
由于while循环在子shell中运行,我期望'index is 0'作为solaris和linux中的输出.但是在solaris中,$ index是/ tmp下包含'e'的实际文件数.那么虽然循环不在solaris下的子shell中运行?我期待两种操作系统都能得到相同的结果..?
我有这个示例代码:
find "$1" ! -regex "$regex" 2>/dev/null | while read line ; do
a="$line"
done
echo ("$a") # prints nothing because of subshell
Run Code Online (Sandbox Code Playgroud)
我需要:
$a
外部(在全局范围内)可见的解决方法我怎样才能做到这一点?有什么简单的解决办法吗?
试试这种方式:
#!/bin/bash
myvals=`psql -d mydb -c "select id from table1 where 't'"`
ssh user1@host1.domain.tld "for i in $myvals; do echo \$i >> values; done"
Run Code Online (Sandbox Code Playgroud)
只要psql只返回一个值,它就可以正常工作.但如果有几个值,我会收到这样的回复:
bash: -c: line 1: syntax error near unexpected token `2'
bash: -c: line 1: `2'
Run Code Online (Sandbox Code Playgroud)
另外,我试图:
myvals='1 2 3'
Run Code Online (Sandbox Code Playgroud)
然后它工作正常:值1 2 3被附加到远程主机上的"values"文件; 没有错误消息.如果我尝试另一个子shell命令,例如myvals = ls /bin
,则会再次出现错误.很明显,$ myvals已经在本地主机上进行了评估,但是什么使得子shell结果如此不同?
我有一个变量,其中有一些行,我想用另一个变量中定义的许多换行符填充它。然而,子外壳似乎正在剥离尾随的换行符。我不能只使用 '\n' ,echo -e
因为这些行可能已经包含需要按原样打印的转义字符。
我发现我可以使用它打印任意数量的换行符。
n=5
yes '' | sed -n "1,${n}p;${n}q"
Run Code Online (Sandbox Code Playgroud)
但是,如果我在子shell 中运行它以将其存储在变量中,则子shell 似乎会去除尾随的换行符。
我可以近似功能,但它很笨拙,并且由于我使用它的方式,我更愿意能够调用echo "$var"
甚至将$var
其自身用于诸如字符串连接之类的事情。一旦删除了变量的最后一行(填充符),这种近似就会遇到与子外壳相同的问题。
这是我的近似值
n=5
var="test"
#I could also just set n=6
cmd="1,$((n+1))p;$((n+1))q"
var="$var$(yes '' | sed -n $cmd; echo .)"
#Now I can use it with
echo "$var" | head -n -1
Run Code Online (Sandbox Code Playgroud)
本质上,我需要一种将许多换行符附加到变量的好方法,然后可以使用 echo 打印该变量。
如果可能的话,我想保持这个 POSIX 兼容,但在这个阶段,bash 解决方案也是可以接受的。我还将它用作工具的一部分,为此我设定了一个挑战,即在保持可读性的同时最小化行数和字符数。但是一旦我有了可行的解决方案,我就可以解决这个问题
我的理解是当我在BASH shell中执行脚本时,使用类似$ ./myscript.sh
子shell的语法启动并且代码在该shell中运行,并且在我的shell上打印STDOUT和STDERR输出,STDIN取自我的shell.这就是脚本的交互方式.
文件" myscript " 的顶行是#!/bin/bash
,这表示用于在脚本文件中执行语法的解释器.
如果我使用语法source myscript.sh
,我的脚本中的代码被"拉"到我当前的环境并在那里执行,而不是在子shell中执行.我无法在我调用的脚本中运行以下代码$ ./myscript.sh
并影响我当前的shell:
#!/bin/bash
PS1='`
if [ $? -eq 0 ];
then echo -n "\[\033[00;35m\]\u\[\033[01;32m\]@\[\033[00;35m\]\h\[\033[00;32m\](\[\033[01;35m\]\W\[\033[01;32m\])\[\033[00;32m\]\$";
else echo -n "\[\033[00;35m\]\u\[\033[01;31m\]@\[\033[00;35m\]\h\[\033[01;31m\](\[\033[35m\]\W\[\033[31m\])\[\033[00;31m\]\$";
fi`\[\033[0m\]'
Run Code Online (Sandbox Code Playgroud)
如果我删除#!/bin/bash
并使用source
此脚本更改我的命令提示符.它可以以一种我可以调用它的方式安排在一个脚本中$ ./myscript.sh
,它会改变我当前的shell,而不是子shell吗?
如何在bash子shell中调用echo?这是我想要的行为:
# w=5
# echo $w > /tmp/x
# cat /tmp/x
5
Run Code Online (Sandbox Code Playgroud)
但:
# cmd="echo $w > /tmp/x"
# $cmd
5 > /tmp/x
Run Code Online (Sandbox Code Playgroud)
和:
# $( $cmd )
bash: 5: command not found
Run Code Online (Sandbox Code Playgroud) 当我直接执行以下命令时:
root@busybox-694d76bb5d-2gcvh:/# mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1'
Run Code Online (Sandbox Code Playgroud)
我得到以下输出:
mysql: [Warning] Using a password on the command line interface can be insecure.
+---+
| 1 |
+---+
| 1 |
+---+
Run Code Online (Sandbox Code Playgroud)
但是,在子 shell 中使用相同的命令,如下所示:
$(mysql -hmariadb -P3306 -uroot -ppassword -e 'SELECT 1')
Run Code Online (Sandbox Code Playgroud)
输出:
mysql: [Warning] Using a password on the command line interface can be insecure.
bash: 1: command not found
Run Code Online (Sandbox Code Playgroud)
为什么 bash 将我作为参数发送的“1”解释为在子 shell 中发送时就好像它是一个单独的命令一样?
是否可以在不通过子shell 的情况下获取当前时间(可能还有日期)?
因为如果我没记错的话,这个命令会打开一个子shell吗?
d=$(date)
Run Code Online (Sandbox Code Playgroud)