在 bash 脚本中循环遍历制表符界定的文件

在 bash 脚本中循环遍历制表符界定的文件

这是我到目前为止所拥有的:

#!/bin/bash
while read line; do
        DB=$(echo $line | cut -f1)
        USER=$(echo $line | cut -f2)
        PASS=$(echo $line | cut -f3)
        echo DB=$DB USER=$USER PASS=$PASS
done < users.txt

以及输入文件的示例:

drupal_1    drupal1 tmmjXSWL
drupal_2    drupal2 FHiJSYHM
drupal_3    drupal3 b7bFNj06
drupal_4    drupal4 0AaV62EL

以及脚本的输出:

DB=drupal_1 drupal1 tmmjXSWL USER=drupal_1 drupal1 tmmjXSWL PASS=drupal_1 drupal1 tmmjXSWL
DB=drupal_2 drupal2 FHiJSYHM USER=drupal_2 drupal2 FHiJSYHM PASS=drupal_2 drupal2 FHiJSYHM
DB=drupal_3 drupal3 b7bFNj06 USER=drupal_3 drupal3 b7bFNj06 PASS=drupal_3 drupal3 b7bFNj06

由于某种原因,每个变量都设置为整行。当我echo users.txt | cut -f1在命令行中使用时,它会很好地返回令牌。

答案1

问题出在命令上echo $line。由于 周围没有引号$line,因此 shell 对其执行分词,然后将每个单词解释为通配模式。尝试一下

a='*.txt foo'
ls $a

在您的情况下,选项卡分隔单词,然后这些单词成为 的单独参数echo。该echo命令打印其参数,并用空格分隔。因此cut最终会收到空格分隔的字段而不是制表符分隔的字段。

$foo始终在变量替换和命令替换两边加上双引号$(foo)(除非您了解为什么需要将它们排除在外以及为什么可以这样做)。echo "$line"在这里可以工作,但这是执行您建议的一种复杂的方式。

保留 shell 中的解析方法,您可以使read命令将输入​​解析为字段。

while read DB USER PASS; do
  echo "DB=$DB USER=$USER PASS=$PASS"
done <users.txt

read拆分变量值中由字符分隔的字段IFS,默认情况下由空格和制表符(加上换行符,不能出现在行内)组成。要仅在选项卡上拆分,请先设置IFS为单个选项卡。请注意,前导和尾随制表符将被忽略,连续的制表符将被视为一个制表符。

read视为\特殊字符:反斜杠后跟换行符将被忽略;\\变成单个反斜杠。如果您想避免这种行为,请传递该-r选项。

答案2

这个怎么样?

$ awk '{print "DB="$1"\tUSER="$2"\tPASS="$3}' users.txt
DB=drupal_1 USER=drupal1    PASS=tmmjXSWL
DB=drupal_2 USER=drupal2    PASS=FHiJSYHM
DB=drupal_3 USER=drupal3    PASS=b7bFNj06
DB=drupal_4 USER=drupal4    PASS=0AaV62EL

我无法判断您是否有问题需要解决,或者想知道更多的理论问题。

相关内容