如何准备带有sed的值对以进行循环?

时间:2019-08-22 12:36:02

标签: bash sed foreach

我写了

for pair in $(my command | sed -En "s/my expression/\1 \2/p"); do
    echo $pair
done

但每行都有所有条目:

host
port
host 
port
...

如果我打印

my command | sed -En "s/my expression/\1 \2/p"

我明白了

host port
host port
host port
...

如何正确准备值对?

3 个答案:

答案 0 :(得分:2)

您正在使用命令替换而不是设置IFS,请尝试:

IFS='\n'
for pair in $(my command | sed -En "s/my expression/\1 \2/p"); do
    echo $pair
done

默认设置是在空格,制表符和换行符之间进行分割。在这里,您只想在换行符上进行拆分,因此您需要将IFS设置为该值,否则意味着如果该对包含空格或制表符,将无法正常工作

答案 1 :(得分:1)

原因很简单,

for pair in $(…)

对空格(在您的情况下包括单个空格)进行迭代。一口气评估了$()中的命令,这些结果为for循环提供了结果,它只会看到您给它的参数列表。因此,在开始for循环之前,请先设置IFS=$'\n'

IFS=$'\n'
for pair in $(…)

答案 2 :(得分:0)

如果这不是一个非常简单的替代词,我会尽量避免使用sedawk的能力更强,同时也更清晰。这是POSIX awk的答案。

my command | awk '{ d="\n"; if (NR%2) d=" "; printf $0 d}'

但是,如果将间距放入command substitution$(…)格式)中,将无法保留间距。要解决此问题,请考虑使用其他成对的定界符,例如将d=" "更改为d=":"

for pair in "$(my command | awk '{ d="\n"; if (NR%2) d=":"; printf $0 d}')"; do
    echo $pair
done

如果您实际上想对一对的不同部分做某事,请使用bash进行整个操作:

line_num=0
while IFS= read line; do
    line_num=$((line_num+1))
    if [ $((line_num%2)) = 1 ]; then
        host="$line"
    else
        port="$line"
        # do things with $host and $port here
        echo "$host $port"
    fi
done < <(my command)