文件参数

文件参数

如何编写一个接受来自文件名参数或标准输入的脚本?

例如,您可以使用less这种方式。可以less filename等效地执行和cat filename | less

有没有一种简单的“开箱即用”方法可以做到这一点?还是我需要重新发明轮子并在脚本中编写一些逻辑?

答案1

如果文件参数是脚本的第一个参数,请测试是否存在参数 ( $1) 并且它是否为文件。否则从 stdin 读取输入 -

因此你的脚本可能包含如下内容:

#!/bin/bash
[ $# -ge 1 -a -f "$1" ] && input="$1" || input="-"
cat $input

例如,您可以像这样调用脚本

./myscript.sh filename

或者

who | ./myscript.sh

编辑 对脚本的一些解释:

[ $# -ge 1 -a -f "$1" ]- 如果至少有一个命令行参数($# -ge 1)AND(-a 运算符)第一个参数是一个文件(-f 测试“$1”是否是一个文件)那么测试结果为真。

&&是 shell 逻辑 AND 运算符。如果测试为真,则分配input="$1"cat $input输出文件。

||是 shell 逻辑或运算符。如果测试为假,则||解析后面的命令。输入被赋值为“-”。命令cat -从键盘读取。

总结一下,如果提供了脚本参数并且它是一个文件,那么变量输入将被分配给文件名。如果没有有效的参数,那么 cat 将从键盘读取。

答案2

read./script <someinput从标准输入读取。从文件 ( ) 或通过管道 ( )重定向dosomething | ./script不会使其工作方式不同。

您所要做的就是循环遍历输入中的所有行(这与遍历文件中的行没有什么区别)。

(示例代码,仅处理一行)

#!/bin/bash

read var
echo $var

将回显标准输入的第一行(通过<|)。

答案3

你没有提到你计划使用什么 shell,因此我假设使用 bash,尽管这些是跨 shell 的相当标准的东西。

文件参数

可以通过变量访问参数$1- $n$0返回用于运行程序的命令)。假设我有一个脚本,它只cat输出 n 个文件,每个文件之间有一个分隔符:

#!/usr/bin/env bash
#
# Parameters:
#    1:   string delimiter between arguments 2-n
#    2-n: file(s) to cat out
for arg in ${@:2} # $@ is the array of arguments, ${@:2} slices it starting at 2.
do
   cat $arg
   echo $1
done

在本例中,我们将文件名传递给 cat。但是,如果你想转换文件中的数据(而不显式写入和重写),你也可以将文件内容存储在变量中:

file_contents=$(cat $filename)
[...do some stuff...]
echo $file_contents >> $new_filename

从标准输入读取

至于从标准输入读取,大多数 shell 都有一个非常标准的read内置命令,尽管在提示符的指定方式上存在差异(至少)。

Bash 内置命令手册页有一个非常简洁的解释read,但我更喜欢打击黑客页。

简单地:

read var_name

多个变量

要设置多个变量,只需提供多个参数名称即可read

read var1 var2 var3

read然后将把来自 stdin 的一个单词放入每个变量中,将所有剩余的单词转储到最后一个变量中。

λ read var1 var2 var3
thing1 thing2 thing3 thing4 thing5
λ echo $var1; echo $var2; echo $var3
thing1
thing2
thing3 thing4 thing5

如果输入的单词数少于变量数,则剩余的变量将为空(即使先前设置过):

λ read var1 var2 var3
thing1 thing2
λ echo $var1; echo $var2; echo $var3
thing1
thing2
# Empty line

提示

-p经常使用标志来提示:

read -p "Enter filename: " filename

注意:ZSH 和 KSH(也许还有其他)使用不同的提示语法:

read "filename?Enter filename: " # Everything following the '?' is the prompt

默认值

这其实不算什么read技巧,但我经常与 结合使用read。例如:

read -p "Y/[N]: " reply
reply=${reply:-N}

基本上,如果变量(reply)存在,则返回其自身,但如果为空,则返回以下参数(“N”)。

答案4

您还可以执行以下操作:

#!/usr/bin/env bash

# Set variable input_file to either $1 or /dev/stdin, in case $1 is empty
# Note that this assumes that you are expecting the file name to operate on on $1
input_file="${1:-/dev/stdin}"

# You can now use "$input_file" as your file to operate on
cat "$input_file"

有关 Bash 中更多巧妙的参数替换技巧,请参阅

相关内容