我创建了一个.bashrc文件,其中有两个功能。一个在while循环中循环遍历文件的每一行。我试图保存行的内容(如果它们符合特定条件),然后将所有三个匹配项传递给第二个函数,然后将它们回显。但是,我尝试了导出变量,还尝试了管道传递给第二个函数,但均无效。管道的行为也很奇怪,我将在代码示例中进行说明。
readAndPipe() {
while read -r line || [[ -n "$line" ]]; do
(
if [[ $line == FIRSTNAME=BOB ]]; then
echo $line;
fi;
if [[ $line == LASTNAME=SMITH ]]; then
echo $line;
fi;
if [[ $line == BIRTHMONTH=AUGUST ]]; then
echo $line;
fi;
); done < "file.txt" | printArguments $1 #pass the original command line argument;
}
printArguments() {
#This is where the weirdness happens
echo $@ #Prints: only the original command line argument
echo $# #Prints: 1
echo $2 $3 $4 #Prints nothing
varName=$(cat $2 $3 $4)
echo $varName #Prints: FIRSTNAME=BOB
# LASTNAME=SMITH
# BIRTHMONTH=AUGUST
cat $2 $3 $4 #Prints nothing
echo $(cat $2 $3 $4) #Prints nothing
cat $2 $3 $4 | tr "\n" '' #Prints tr: empty string2
}
显然我不是bash专家,所以我确定这里有很多错误,但是我想知道的是
答案 0 :(得分:1)
$@
,$*
,$1
,$2
等是传递给函数的自变量。例如,在myfunc foo bar baz
中,我们有$ 1 == foo,$ 2 == bar和$ 3 == baz。
将数据管道传输到函数时,必须从stdin中检索数据:
myfunc() {
data=$(cat)
echo "I received: >$data<"
}
for n in {1..5}; do echo "x=$n"; done | myfunc
产生
I received: >x=1
x=2
x=3
x=4
x=5<
varName=$(cat $2 $3 $4)
之所以有效,是因为$ 2 $ 3和$ 4 为空,因此外壳程序会看到以下内容:
varName=$(cat )
cat之所以只能使用一次,是因为您消费一个流。一旦消耗掉,它就消失了。 "you can't eat your cake and have it too."
printArguments
函数可以使用readarray
命令将到来的行抓取到一个数组中,而不是使用cat
将所有到来的文本抓取到一个变量中:
printArguments() {
readarray -t lines
echo "I have ${#lines[@]} lines"
echo "they are:"
printf ">>%s\n" "${lines[@]}"
}
{ echo foo; echo bar; echo baz; } | printArguments
输出
I have 3 lines
they are:
>>foo
>>bar
>>baz
在交互式bash提示符下键入help readarray
了解更多信息。
答案 1 :(得分:1)
想象一个脚本:
func() {
echo $# # will print 2, func were executed with 2 arguments
echo "$@" # will print `arg1 arg2`, ie. the function arguments
in=$(cat) # will pass stdin to `cat` function and save cat's stdout into a variable
echo "$in" # will print `1 2 3`
}
echo 1 2 3 | func arg1 arg2
# ^^^^^^ function `func` arguments
# ^ passed one command stdout to other command stdin
# ^^^ outputs `1 2 3` on process stdout
cat
在不带任何参数的情况下调用,读取stdin
并将其输出到stdout
。in=$(cat)
会像普通cat
一样读标准输入,只是将输出(即cat
的标准输出)保存到变量中)到您的脚本:
readAndPipe() {
# the while read line does not matter, but it outputs something on stdout
while read -r line || [[ -n "$line" ]]; do
echo print something
# the content of `file.txt` is passed as while read input
done < "file.txt" | printArguments $1 # the `print something` (the while loop stdout output) is passed as stdin to the printArguments function
}
printArguments() {
# here $# is equal to 1
# $1 is equal to passed $1 (unless expanded, will get to that)
# $2 $3 $4 expand to nothing
varName=$(cat $2 $3 $4) # this executes varName=$(cat) as $2 $3 $4 expand to nothing
# now after this point stdin has been read (it can be read once, it's a stream or pipe
# is you execute `cat` again it will block (waiting for more input) or fail (will receive EOF - end of file)
echo $varName #Prints: `print something` as it was passed on stdin to this function
}
如果文件file.txt
仅包含:
FIRSTNAME=BOB
LASTNAME=SMITH
BIRTHMONTH=AUGUST
您可以只加载文件. file.txt
或source file.txt
。这将“加载”文件,即。使其成为脚本的一部分,语法就是bash。因此您可以:
. file.txt
echo "$FIRSTNAME"
echo "$LASTNAME"
echo "$BIRTHMONTH"
这是在/ etc /中创建配置文件的通用方法,然后由脚本加载它们。这就是为什么在许多/ etc /文件中注释都以#
开头的原因。
注意: