我知道可以为单个命令/内置的范围设置自定义 IFS 值。有没有办法为单个语句设置自定义 IFS 值?显然不是,因为根据下面的尝试,全局 IFS 值会受到影响
#check environment IFS value, it is space-tab-newline
printf "%s" "$IFS" | od -bc
0000000 040 011 012
\t \n
0000003
#invoke built-in with custom IFS
IFS=$'\n' read -r -d '' -a arr <<< "$str"
#environment IFS value remains unchanged as seen below
printf "%s" "$IFS" | od -bc
0000000 040 011 012
\t \n
0000003
#now attempt to set IFS for a single statement
IFS=$'\n' a=($str)
#BUT environment IFS value is overwritten as …Run Code Online (Sandbox Code Playgroud) 根据此,将花括号之间的命令列表导致在当前外壳上下文要执行的列表。没有创建子shell。
用ps看到这个在行动
这是直接在命令行上执行的流程管道的流程层次结构。4398 是登录 shell 的 PID:
sleep 2 | ps -H;
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29696 pts/23 00:00:00 sleep
29697 pts/23 00:00:00 ps
Run Code Online (Sandbox Code Playgroud)
现在遵循直接在命令行上执行的大括号之间的流程管道的流程层次结构。4398 是登录 shell 的 PID。它类似于上面证明所有内容都在当前 shell 上下文中执行的层次结构:
{ sleep 2 | ps -H; }
PID TTY TIME CMD
4398 pts/23 00:00:00 bash
29588 pts/23 00:00:00 sleep
29589 pts/23 00:00:00 ps
Run Code Online (Sandbox Code Playgroud)
现在,这是sleep管道中本身放置在大括号内时的流程层次结构(因此总共有两级大括号)
{ { sleep 2; } | ps -H; }
PID TTY …Run Code Online (Sandbox Code Playgroud) 我正在寻找一个命令或脚本来执行以下操作 - 给定:
文件1.txt:
abcd
efgh
ijkl
mnop
Run Code Online (Sandbox Code Playgroud)
文件2.txt:
123abcd123
123efgh123
123mnop123
Run Code Online (Sandbox Code Playgroud)
我想要一个执行以下操作的命令:
ungrep file1.txt file2.txt
Run Code Online (Sandbox Code Playgroud)
并返回以下内容:
ijkl
Run Code Online (Sandbox Code Playgroud)
换句话说,它给了我 file1.txt 中的行,这些行不会在 file2.txt 的 grep 上返回任何结果。我知道我可以通过遍历 file1.txt,为每一行 grepping file2.txt 并存储结果,并输出结果为空的任何行来做到这一点,但我希望有一种更有效的方法来做到这一点。
这是我最常做的运行grep,并wc在一个文件,而无需扫描两次
<file.txt tee >(grep LITERAL) >(wc -l) >/dev/null
Run Code Online (Sandbox Code Playgroud)
然而,这会产生
EXEC LITERAL
32
Run Code Online (Sandbox Code Playgroud)
有时和
32
EXEC LITERAL
Run Code Online (Sandbox Code Playgroud)
在其他时间。(第一个实例中grepfrom的输出先于from的输出,wc在第二个实例中反之亦然。)
另一方面,使用重定向和文件描述符
{ { <file.txt tee /dev/fd/3 | grep LITERAL >&4; } 3>&1 | wc -l ;} 4>&1
Run Code Online (Sandbox Code Playgroud)
我似乎总是得到
EXEC LITERAL
32
Run Code Online (Sandbox Code Playgroud)
我更喜欢输出顺序是可预测的,但是第二种方法可以保证吗?
我想将 ls 命令的输出捕获到一个文件中
ls >> lsOutput.log
Run Code Online (Sandbox Code Playgroud)
如果在命令行中执行,则此方法有效。但是当放入 shell 脚本 ( lsOutput.sh) 时,返回
./lsOutput.sh: 3: ./lsOutput.sh: total: not found
Run Code Online (Sandbox Code Playgroud)
lsOutput.sh 代码
#!/bin/sh
`ls -lrt` >> lsOutput.log
Run Code Online (Sandbox Code Playgroud) 在 bash 中,是[[ $variable ]]和[[ -n $variable ]]完全等价的吗?从下面的输出来看,情况似乎是这样,但我看到两种形式的用法在 shell 脚本中都很普遍。
$ z="abra"
$ [[ $z ]]
$ echo $?
0
$ [[ -n $z ]]
$ echo $?
0
$ z=""
$ [[ $z ]]
$ echo $?
1
$ [[ -n $z ]]
$ echo $?
1
$ unset z
$ [[ $z ]]
$ echo $?
1
$ [[ -n $z ]]
$ echo $?
1
Run Code Online (Sandbox Code Playgroud) stdbuf 命令的手册页指出,行缓冲模式作为标准输入缓冲选项无效。这是什么原因?
tail -f access.log | stdbuf -iL cut -d' ' -f1 | uniq
stdbuf: line buffering stdin is meaningless
Try `stdbuf --help' for more information.
Run Code Online (Sandbox Code Playgroud) 我遇到的用转换后的输出替换输入文件的内容的解决方案涉及使用临时文件或海绵实用程序。
Stephane Chazelas 在这里的回答指出了另一种涉及以读写模式打开文件的方法,如下所示。
tr ' ' '\t' < file 1<> file
Run Code Online (Sandbox Code Playgroud)
这实际上如何在不损坏相关文件的情况下工作?
我尝试过 find -name 'a*' 'z*' '*a' '*z'
但它给了我错误代码 find: paths must precede expression: z*
我知道如何查找以 z 开头或以 az 结尾但不以特定字母开头的文件。
需要做什么来确保在命令替换中使用包含嵌入空格的参数时正确处理?也许一个例子可以说明
$ file="/home/1_cr/xy z"
$ basename $file
xy
$ #need to pass basename a quoted $file to prevent the z in 'xy z' from being eaten
$ basename "$file"
xy z
$ #Now using $file inside a command substitution without quoting.....
$ #....the command substitution causes 'xy z' to split
$ set -- $(basename "$file")
$ printf "%s\n" "$@"
xy
z
$ #But quoting the command substitution does not prevent 'xy z'......
$ #....from being split before being passed to …Run Code Online (Sandbox Code Playgroud)