在bash中使用分隔符为变量指定行

在bash中使用分隔符为变量指定行,bash,grep,ifs,Bash,Grep,Ifs,我有一个从grep输出生成的文件,它看起来像这样: http://google.fr Pierre google http://test.fr -- http://yahoo.com Jean Yahoo http://test.fr -- 我为每3行做了一个分隔符'--'。我想将每一行分配给一个变量,例如: url= "http://google.fr" name= "Pierre Google" web= "http://test.fr" 因此,我使用IFS=--创建了bash脚本,并尝

我有一个从grep输出生成的文件,它看起来像这样:

http://google.fr
Pierre google
http://test.fr
--
http://yahoo.com
Jean Yahoo
http://test.fr
--
我为每3行做了一个分隔符'--'。我想将每一行分配给一个变量,例如:

url= "http://google.fr"
name= "Pierre Google"
web= "http://test.fr"
因此,我使用IFS=--创建了bash脚本,并尝试使用echo的-d选项,但我不知道如何为每个块将这3行赋值给变量


感谢您的帮助

和一些错误处理,这可能看起来像:

while read -r url && read -r name && read -r web; do
  echo "Read url of $url, name of $name, and web of $web"
  read -r sep || { true; break; } # nothing to read: exit loop w/ successful $?
  if [[ $sep != -- ]]; then
    printf 'Expected separator, but saw: %q\n' "$sep" >&2
    false; break # "--" not seen where expected; exit loop w/ $? indicating failure
  fi
done <in.txt
read-r url&&read-r name&&read-r web;做
echo“读取$url的url,读取$name的名称,读取$web的web”
read-r sep | |{true;break;}#无需读取:退出循环w/successful$?
如果[$sep!=--];然后
printf'需要分隔符,但看到了:%q\n'$sep'>&2
错误的打破#“--”在预期的地方看不到;退出循环w/$?指示故障
fi

通过一点错误处理,这可能看起来像:

while read -r url && read -r name && read -r web; do
  echo "Read url of $url, name of $name, and web of $web"
  read -r sep || { true; break; } # nothing to read: exit loop w/ successful $?
  if [[ $sep != -- ]]; then
    printf 'Expected separator, but saw: %q\n' "$sep" >&2
    false; break # "--" not seen where expected; exit loop w/ $? indicating failure
  fi
done <in.txt
read-r url&&read-r name&&read-r web;做
echo“读取$url的url,读取$name的名称,读取$web的web”
read-r sep | |{true;break;}#无需读取:退出循环w/successful$?
如果[$sep!=--];然后
printf'需要分隔符,但看到了:%q\n'$sep'>&2
错误的打破#“--”在预期的地方看不到;退出循环w/$?指示故障
fi

完成这应该适合你的情况

    NR=0
    while read LINE; do
        ((NR++))
        case $NR in
            1)
                URL=$LINE
                    ;;
            2)
                NAME=$LINE
                    ;;
            3)
                WEB=$LINE
                    ;;
            4)
                if [ $LINE = "--" ]; then
                    NR=0
                    #
                    # DO WHAT EVER YOU WANT TO DO WITH YOUR DATA HERE
                    #
                    #
                    echo "$URL;;$NAME;;$WEB"
                else
                    echo "wrong delimiter found \"$LINE\""
                fi
                    ;;
        esac
    done
用它运行

script.sh < inputfile.txt
script.sh

或者将grep命令的输出通过管道传输到脚本。

这应该适用于您的情况

    NR=0
    while read LINE; do
        ((NR++))
        case $NR in
            1)
                URL=$LINE
                    ;;
            2)
                NAME=$LINE
                    ;;
            3)
                WEB=$LINE
                    ;;
            4)
                if [ $LINE = "--" ]; then
                    NR=0
                    #
                    # DO WHAT EVER YOU WANT TO DO WITH YOUR DATA HERE
                    #
                    #
                    echo "$URL;;$NAME;;$WEB"
                else
                    echo "wrong delimiter found \"$LINE\""
                fi
                    ;;
        esac
    done
用它运行

script.sh < inputfile.txt
script.sh

或者只需将grep命令的输出通过管道传输到脚本。

您可以将文件预处理为更典型的格式,使用IFS使用实用程序(如
awk
sed
)将其分离为字段(或变量):

while IFS="|" read -r url name web; do
    echo "$url" "$name" "$web"
done  < <(awk 'BEGIN{RS="--\n"; FS="\n"; OFS="|"} {print $1,$2,$3}' file)

您可以将文件预处理为更典型的格式,以使用IFS,使用诸如
awk
sed
之类的实用程序将其分离为字段(或变量):

while IFS="|" read -r url name web; do
    echo "$url" "$name" "$web"
done  < <(awk 'BEGIN{RS="--\n"; FS="\n"; OFS="|"} {print $1,$2,$3}' file)

IFS
是无序的字符集合<代码>-
-
完全相同。类似地,
-d
的后续参数是单个字符。要准确解释您使用的
读取
功能不起作用的原因,我们需要查看它,但也很难看到单个
读取
功能在这里是正确的。(我想我们可以使用
IFS=$'\n'read-r-d--a片段
之类的,然后接受其他所有结果都是空的)http://google.fr“
实际运行
http://google.fr
作为带有
url的命令,以空值导出到环境中。这样的赋值应该是
url=”http://google.fr“
,不带空格。
IFS
是无序的字符集合<代码>-
-
完全相同。类似地,
-d
的后续参数是单个字符。要准确解释您使用的
读取
功能不起作用的原因,我们需要查看它,但也很难看到单个
读取
功能在这里是正确的。(我想我们可以使用
IFS=$'\n'read-r-d--a片段
之类的,然后接受其他所有结果都是空的)http://google.fr“
实际运行
http://google.fr
作为带有
url的命令,以空值导出到环境中。这样的赋值应该是
url=”http://google.fr“
,没有空格。8分钟太慢:-)几条注释。首先——所有caps变量名都是为对操作系统或shell有意义的变量保留的;应用程序定义的变量名称中至少应有一个小写字符。请参阅中的相关POSIX指南,记住shell变量和环境变量共享一个名称空间。第二,您引用的正是
[$LINE=“--”]
中的内容;
--
字符串只能在不带引号的情况下对其自身求值,但是
$LINE
不带引号的字符串可能会变成零个或多个单词。例如,如果您有一行包含
*
,它将被文件名列表替换,因此您将运行类似于
[a.txt b.txt=-]
的内容,这是无效的
测试
语法,并且会在stderr上产生错误。类似地,
[=-]
(这将导致空行)将产生错误,因为
=
作为一元运算符无效<代码>[“$LINE”=-->
可以避免这种问题。(另外,我建议使用
-r
参数来
读取
,除非您有特定的理由不这样做:如果没有
-r
,输入中的反斜杠将被解释为行连续体,因此如果您的名称以反斜杠结尾,那么您将在下一行中的网址以相同的
读取
返回。)如果您不想在代码运行时使用
set-e
.8分钟太慢:-)一些注释,请使用
((++NR))
而不是
((NR++)
)。首先——所有caps变量名都是为对操作系统或shell有意义的变量保留的;应用程序定义的变量名称中至少应有一个小写字符。请参阅中的相关POSIX指南,记住shell变量和环境变量共享一个名称空间。第二,您引用的正是
[$LINE=“--”]
中的内容;
--
字符串只能在不带引号的情况下对其自身求值,但是
$LINE
不带引号的字符串可能会变成零个或多个单词。例如,如果您有一行包含
*
,它将被文件名列表替换,因此您将运行类似于
[a.txt b.txt=-]
的内容,这是无效的
测试
语法,并且会在stderr上产生错误。类似地,
[=--]
(这将导致空行)将产生错误,因为
=
无效