如何从bash中的文件循环打印2列

问题描述

我有以下output.txt,它仅包含2列来演示:

Test1 Test1-IS-OK
Test2 Test2-IS-NOT
Test3 Test3-IS-OK
Test4 Test4-IS-OK
Test5 Test5-IS-NOT

然后我的bash脚本具有以下代码:

#!/bin/bash
output="output.txt"
a=$(awk '{ print $1 }' $output)
b=$(awk '{ print $2 }' $output)

while IFS=" " read -r $a $b
do
    echo "LOG: $a and $b"
done < "$output"

我遇到以下错误:

./test.sh: line 13: read: `Test1-IS-OK': not a valid identifier

我需要这样的输出

LOG: Test1 and Test1-IS-OK
LOG: Test2 and Test2-IS-NOT
LOG: Test3 and Test3-IS-OK
LOG: Test4 and Test4-IS-OK
LOG: Test5 and Test5-IS-NOT

但是代码不起作用。从文件中循环这两列的最佳方法是什么?有没有更简单的方法?

解决方法

最好是避免bash并完全在awk中完成。在awk中,它很简单:

awk '{print "LOG:",$1,"and",$2}' file
LOG: Test1 and Test1-IS-OK
LOG: Test2 and Test2-IS-NOT
LOG: Test3 and Test3-IS-OK
LOG: Test4 and Test4-IS-OK
LOG: Test5 and Test5-IS-NOT
,

请考虑将awk解析转移到它所属的循环中:

#!/bin/bash

output="output.txt"

while read -r line 
do
    a=$(echo "${line}" | awk '{print $1}')
    b=$(echo "${line}" | awk '{print $2}')
    echo "LOG: $a and $b"
done < "$output"

根据@EdMorton的很好建议进行编辑

,

您的代码有什么问题?

a=$(awk '{ print $1 }' $output)

使用echo "a=${a}",您将看到a填充了所有行的输出。您正在尝试找出要在$a之后调用的函数。

while IFS=" " read -r $a $b

现在,您正在尝试调用“功能” a和b。该代码将在读取输入文件之前替换变量的值。当用“ Test1 Test2”填充a时,代码将尝试填充$Test1$Test2字段。

当您只想更改输出而不将变量传递到另一条语句时,可以使用awk

sed -E 's/([^ ]*) ([^ ]*).*/LOG: \1 and \2/' $output
# or
printf 'LOG: %s and %s\n' $(<$output)

对于您而言,您可以使read读取两个参数:

while read -r a b 
do
    echo "LOG: $a and $b"
done < "$output"
,

使用此Perl单线版:

perl -lane 'print "LOG: $F[0] and $F[1]";' output.txt > new.txt

Perl单行代码使用以下命令行标志:
-e:告诉Perl在代码中而不是在文件中查找代码。
-n:一次遍历输入一行,默认情况下将其分配给$_
-l:在直接执行代码之前,先剥离输入行分隔符(默认为* NIX上的"\n"),并在打印时附加它。 -a:在空白或$_选项中指定的正则表达式上,将@F拆分为数组-F

另请参见:
perldoc perlrun: how to execute the Perl interpreter: command line switches

相关问答

错误1:Request method ‘DELETE‘ not supported 错误还原:...
错误1:启动docker镜像时报错:Error response from daemon:...
错误1:private field ‘xxx‘ is never assigned 按Alt...
报错如下,通过源不能下载,最后警告pip需升级版本 Requirem...