在 POSIX shell 中使用while 循环来处理文本通常被认为是不好的做法吗?
正如Stéphane Chazelas 所指出的,不使用 shell 循环的一些原因是概念、可靠性、易读性、性能和安全性。
这个答案解释了可靠性和易读性方面:
while IFS= read -r line <&3; do
printf '%s\n' "$line"
done 3< "$InputFile"
Run Code Online (Sandbox Code Playgroud)
为了性能,从文件或管道读取时,while循环和读取非常慢,因为内置的read shell一次读取一个字符。
怎么样的概念和安全性方面?
我必须以这种格式获取 IP 地址列表(负载):
134.27.128.0
111.245.48.0
109.21.244.0
Run Code Online (Sandbox Code Playgroud)
并将它们转换为这种格式,中间有一个管道(IP 组成)
134.27.128.0 | 111.245.48.0 | 109.21.244.0 | 103.22.200.0/22
Run Code Online (Sandbox Code Playgroud)
我认为这是一个查找和替换命令,sed但我无法让它工作。
我在文件中有测试数据 text.txt
a
b
test
test2
1,2
3,3
Run Code Online (Sandbox Code Playgroud)
我想从 test 为 + 2 的行号开始输出文件。我需要这是一个可用的单行gnuplot,我想出了以下内容:
awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename
Run Code Online (Sandbox Code Playgroud)
但我需要以某种方式将文件内容提供给两个awk我不知道该怎么做的。所以我想出了解决方案,$filename但这有问题,如何进入$filename。
我在想:
echo "test.txt" | read filename | awk -v linestart=$(awk '$0~"test" {a=NR}END{print a+2}' $filename) 'BEGIN{FS=",";OFS="\t";lines}NR>=linestart{print $1, $2}' $filename
Run Code Online (Sandbox Code Playgroud)
但这不起作用。
我还能如何使上述工作?明显的问题是我需要在运行之前知道要开始打印的行号awk。我也在想一些事情:
awk 'BEGIN{FS=",";OFS="\t";lines=100000}{if ($0~"test"){lines=NR+2}; if(NR>=lines){print $1, $2}}'
Run Code Online (Sandbox Code Playgroud)
但是我什至没有尝试过,因为它非常丑陋且不通用,我必须使变量lines始终足够大。那么是否有一个优雅的解决方案可以与普通的文本文件管道一起使用,或者在其他情况下以某种方式将文件名推入其中?
我的问题与此相反。
我的输入文件是位置和序列号的列表(如库存列表)。一些序列号被列为范围(例如,11-17),我需要将每个范围转换为序列号的完整列表(例如,11、12、13、14、15、16、17)。
输入格式是这样的:
Main Street # 12770-12786, 12980, 13012-13013, 13068, 13093, 13115, 13122, 13137-13156, 13548-13557, 13954-13969, 14471-14475, 14500-14508
Madison Ave # 14071-14074, 14105-14128, 14131-14140, 14603-14612
Run Code Online (Sandbox Code Playgroud)
每个位置由一个空行分隔。每个位置都以名称开头。到目前为止,我只看到包含[a-zA-Z -]大小写字母、空格和破折号的名称。名称从新行的第 0 列开始,后跟一个空格、一个散列和一个空格:#。
对于格式中的每个范围nnnn-mmmm,我需要生成一个逗号(和空格)分隔的顺序值列表,例如n1, n2, n3, n4, n5. 例如,Madison Ave(上图)的库存需要像这样列出:
Madison Ave # 14071, 14072, 14073, 14074, 14105, 14106, 14107, etc.
Run Code Online (Sandbox Code Playgroud)
输入是一个文本文件,输出可以是一个文本文件。我想在 bash 中进行处理,但我想我也可以使用 Python。
我知道一些可能的解决方案,例如:
使用这样的正则表达式模式使用 grep 查找范围:
grep -o -P '\d+-\d+'<input_file>
Run Code Online (Sandbox Code Playgroud)假设第一个结果是范围 4243-4263
echo {4243-4263} | sed 's/-/../'
Run Code Online (Sandbox Code Playgroud)对上述结果使用 for 循环,如下所示:
for …Run Code Online (Sandbox Code Playgroud)