【问题标题】:Reading each line as argument in bash在bash中读取每一行作为参数
【发布时间】:2014-06-10 13:30:30
【问题描述】:

我正在努力学习抨击。我正在尝试运行 ./test 测试用例 测试用例中的文件在下一行有参数 9 11 22 13、32 35 32 16 等等 我的程序需要 4 个参数。现在,如果测试用例有一行参数,即 3 5 6 7 它可以正常工作,但是当有超过 2 个时它无法正常运行程序。我知道我需要一个while循环来读取文件的每一行,但我被困在这里。如果有人可以帮助我,将不胜感激。先感谢您。 之前在这里问过这个问题,不知道大家是不是太忙了,还是不知道怎么做。再次感谢

your_path=../test/test
test_path=../../public/test    
file_input="$1"
#while read -r line; do
#done < "$file_input"

# Read contents in the file
contents=$(< "$file_input")
# Display output of the test file
"$test_path" $contents > correctanswer 2>&1
# Display output of your file
"$your_path" $contents > youranswer 2>&1
diff the solutions
diff correctanswer youranswer > /dev/null 2>&1
if [ $? -eq 0 ]
then
  echo "The two outputs were exactly the same "
else
  echo "$divider"
  echo "The two outputs were different "
  diff youranswer correctanswer
  echo "Do you wish to see the ouputs side-by-side?"
      select yn in "Yes" "No"; do
      case $yn in
         Yes ) echo "LEFT: Your Output   RIGHT: Solution Output"
               sleep 1
               vimdiff youranswer correctanswer; break;;
         No ) exit;;
      esac
      done
fi

【问题讨论】:

标签: bash shell scripting compilation command


【解决方案1】:

我认为你可以这样做:

your_path=../test/test
test_path=../../public/test    
file_input="$1"
while read -r -u 3 contents
do
    # Display output of the test file
    "$test_path" $contents > correctanswer 2>&1
    # Display output of your file
    "$your_path" $contents > youranswer 2>&1
    # diff the solutions
    diff correctanswer youranswer > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "The two outputs were exactly the same "
    else
        echo "$divider"
        echo "The two outputs were different "
        diff youranswer correctanswer
        echo "Do you wish to see the ouputs side-by-side?"
        select yn in "Yes" "No"; do
            case $yn in
                Yes)  echo "LEFT: Your Output   RIGHT: Solution Output"
                      sleep 1
                      vimdiff youranswer correctanswer
                      break;;
                 No)  exit;;
            esac
        done
    fi
done 3< "$file_input"

修改后read 命令读取文件描述符 3,为select 等保留标准输入。


我不知道你在做什么导致它失败。我创建了两个程序,test1 和 test2。最初,它们是相同的:

printf "%s\n" "$@"

然后我更改了test2,所以它包含:

printf "%s\n" "1$@2"

有了input.file中的这些数据:

9 11 22 13
2 35 32 16

我运行了脚本botched.sh:

$ bash -x botched.sh input.file
+ '[' -f /etc/bashrc ']'
+ . /etc/bashrc
++ '[' -z '' ']'
++ return
+ alias 'r=fc -e -'
+ your_path=./test1
+ test_path=./test2
+ file_input=input.file
+ read -r -u 3 contents
+ ./test2 9 11 22 13
+ ./test1 9 11 22 13
+ diff correctanswer youranswer
+ '[' 0 -eq 0 ']'
+ echo 'The two outputs were exactly the same '
The two outputs were exactly the same 
+ read -r -u 3 contents
+ ./test2 2 35 32 16
+ ./test1 2 35 32 16
+ diff correctanswer youranswer
+ '[' 0 -eq 0 ']'
+ echo 'The two outputs were exactly the same '
The two outputs were exactly the same 
+ read -r -u 3 contents
$

正如您所料,输出被识别为相同。然后使用修改后的test2,我重新运行它:

$ bash -x botched.sh input.file
+ '[' -f /etc/bashrc ']'
+ . /etc/bashrc
++ '[' -z '' ']'
++ return
+ alias 'r=fc -e -'
+ your_path=./test1
+ test_path=./test2
+ file_input=input.file
+ read -r -u 3 contents
+ ./test2 9 11 22 13
+ ./test1 9 11 22 13
+ diff correctanswer youranswer
+ '[' 1 -eq 0 ']'
+ echo ''

+ echo 'The two outputs were different '
The two outputs were different 
+ diff youranswer correctanswer
1c1
< 9
---
> 19
4c4
< 13
---
> 132
+ echo 'Do you wish to see the ouputs side-by-side?'
Do you wish to see the ouputs side-by-side?
+ select yn in '"Yes"' '"No"'
1) Yes
2) No
#? 1
+ case $yn in
+ echo 'LEFT: Your Output   RIGHT: Solution Output'
LEFT: Your Output   RIGHT: Solution Output
+ sleep 1
+ vimdiff youranswer correctanswer
2 files to edit
+ break
+ read -r -u 3 contents
+ ./test2 2 35 32 16
+ ./test1 2 35 32 16
+ diff correctanswer youranswer
+ '[' 1 -eq 0 ']'
+ echo ''

+ echo 'The two outputs were different '
The two outputs were different 
+ diff youranswer correctanswer
1c1
< 2
---
> 12
4c4
< 16
---
> 162
+ echo 'Do you wish to see the ouputs side-by-side?'
Do you wish to see the ouputs side-by-side?
+ select yn in '"Yes"' '"No"'
1) Yes
2) No
#? 2
+ case $yn in
+ exit
$

vimdiff 程序确实运行并显示了差异。

注意基本的调试技术——使用bash -x 运行。它表明读取正在使用带有四个数字的单行输入,然后将它们传递给代理程序test1 和test2;然后它需要第二行,并将它们传递给代理程序。

实际测试代码:

your_path=./test1 #../test/test
test_path=./test2 #../../public/test    
file_input="$1"
while read -r -u 3 contents
do
    # Display output of the test file
    "$test_path" $contents > correctanswer 2>&1
    # Display output of your file
    "$your_path" $contents > youranswer 2>&1
    # diff the solutions
    diff correctanswer youranswer > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
        echo "The two outputs were exactly the same "
    else
        echo "$divider"
        echo "The two outputs were different "
        diff youranswer correctanswer
        echo "Do you wish to see the ouputs side-by-side?"
        select yn in "Yes" "No"; do
            case $yn in
                Yes)  echo "LEFT: Your Output   RIGHT: Solution Output"
                      sleep 1
                      vimdiff youranswer correctanswer
                      break;;
                 No)  exit;;
            esac
        done
    fi
done 3< "$file_input"

在 Mac OS X 10.9.2 上使用 Bash 3.2.51 测试。

如果它对您不起作用,那么您需要设置与我的类似的替代测试程序,并显示您在脚本上运行 bash -x 所获得的结果。您还应该确定您正在运行的平台以及您正在运行的 Bash 版本。

【讨论】:

  • 你的问题和其他人一样。一旦我将其更改为此代码,程序就会说使用问题没有输入正确数量的输入。我像 ./test testcase 一样运行它,并且在文件 testcase 中的第 1 行中的数字 3 4 5 6 第 2 行中的 5 6 7 8 它不起作用读取多行
  • 我不知道你在做什么让它不适合你。我已经用对我有用的证据更新了我的答案,确定了这在平台和 Bash 版本方面的含义。您需要提供可比较的证据证明您出了什么问题。
  • 使用 4.1.11(2)-release
  • 当我运行它时 ./test testcase
  • 如果您不向我们展示整个脚本,我们将无法调试您的脚本。问题中的代码中没有“使用错误”!你坚持多少个论点?而且你有太多的东西叫做test。你确实意识到test 是一个内置的shell,不是吗?因此,通常最好避免将其作为脚本名称,因为如果您不每次都使用显式路径名调用它,则会造成严重破坏。我不知道您的../test/test 是否与您的./test 程序相同;它开始听起来好像是。而且你还有../../public/test 作为另一个。
【解决方案2】:

我通常会使用类似于以下的构造(适用于您的示例)。请注意,您需要进行的唯一更改是 cat $file | (while read l; do 然后 done) 关闭循环。循环的主体正是您的代码,但contents 被替换为l(行读取)。循环周围的括号实际上会启动另一个 shell 实例,在该实例中执行 while 并且其 stdin 设置为从 cat 提供。

your_path=../test/test
test_path=../../public/test    
file_input="$1"

exec 3< $file_input
while read -u 3 l; do
# do your per-test diffs and outputs here
# variable $l will contain one line of $file_input
    # Display output of the test file
    "$test_path" $l > correctanswer 2>&1
    # Display output of your file
    "$your_path" $l > youranswer 2>&1
    # diff the solutions
    diff correctanswer youranswer > /dev/null 2>&1
    if [ $? -eq 0 ]
    then
      echo "The two outputs were exactly the same "
    else
      echo "$divider"
      echo "The two outputs were different "
      diff youranswer correctanswer
      echo "Do you wish to see the ouputs side-by-side?"
          select yn in "Yes" "No"; do
          case $yn in
             Yes ) echo "LEFT: Your Output   RIGHT: Solution Output"
                   sleep 1
                   vimdiff youranswer correctanswer; break;;
             No ) exit;;
          esac
          done
    fi

done

【讨论】:

  • 这种工作,但它不会让我在进入 else 后输入 Yes 或 No
  • 对。与您使用的 stdin 相同。因此,不要使用整个 cat $file_input | (while read l; do 构造,而是使用以下内容:exec 3&lt; $file_input; while read -u 3 l; do 并在末尾删除 done 之后的括号。
  • 它仍然有同样的问题,例如如果我运行 ./test testcase 并且 testcase 有 2 行 4 个参数,它不会一一运行。输入也不正确,甚至没有将其作为参数,因为编译器给了我使用问题。在测试用例文件中,我有 4 个整数 5 4 15 32,我的程序需要 4 个整数。通常我使用 ./program 5 4 15 32 运行它,它会添加它们,但它给我一个使用问题。
  • @user3281743:您必须向我们展示bash -x yourscript datafile 的输出。您还需要确定您正在使用哪个版本的 Bash 以及您正在使用它的环境。这个答案与我的基本相同,并且我已经证明它可以工作。
猜你喜欢
  • 1970-01-01
  • 2014-03-02
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-11-28
  • 1970-01-01
  • 2021-08-30
  • 1970-01-01
相关资源
最近更新 更多