awk,bin / sh 0:1:找不到

时间:2015-09-03 20:44:02

标签: bash shell awk

我对编码几乎是全新的,我会很感激反馈。我正在尝试制作一个shell脚本,它将评估文本文件中的信息,并在满足某些条件时移动所述文本文件。我的代码如下:

#!/bin/bash

stock=HD

awk ' /Rank/ {
    if ( $4 == "1-Strong" ) system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt") ;
    else if ( $4 == "2-Buy" ) system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/2/"'$stock'.txt") ;
    else if ( $4 == "3-Hold" ) system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/3/"'$stock'.txt") ;
    else if ( $4 == "4-Sell" ) system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/4/"'$stock'.txt") ;
    else if ( $4 == "5-Strong" ) system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/5/"'$stock'.txt")
} ' $stock.txt

当我尝试运行脚本时,出现此错误:

andrew@andrew-VirtualBox:~/Desktop/Stocks$ ./stockscript7.sh
/bin/sh: 1: 0: not found

我确定我在bash shell中。我确实使用chmod来赋予脚本权限。否则,从这个错误消息我失去了下一步尝试。任何帮助将不胜感激。

3 个答案:

答案 0 :(得分:3)

以下是对本机bash的翻译,没有任何与滥用awk相关的错误(考虑使用名为EVIL'$(rm -rf .)'.txt的输入文件会发生什么 - 使用命令{{1创建}}):

touch $'EVIL\'$(rm -rf .)\'.txt'

然而,这并没有多大意义,因为它写了:你在匹配#!/bin/bash stock=HD while IFS= read -r line; do [[ $line = *Rank* ]] || continue read -r _ _ _ rank _ <<<"$line" case $rank in 1-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/1/ ;; 2-Buy) mv -- "$stock.txt" ~/Desktop/Stocks/2/ ;; 3-Hold) mv -- "$stock.txt" ~/Desktop/Stocks/3/ ;; 4-Sell) mv -- "$stock.txt" ~/Desktop/Stocks/4/ ;; 5-Strong) mv -- "$stock.txt" ~/Desktop/Stocks/5/ ;; esac done <"$stock.txt" 的文件中每行运行一个mv - 但你可以& #39; t多次成功移动单个文件。也许您只想阅读包含Rank第一个行,并根据第四列中的短划线前面的数字重命名该文件?

Rank

说明:

  • #!/bin/bash stock=HD if read -r _ _ _ rating _ < <(grep -e Rank "$stock.txt") && [[ $rating ]]; then mv -- "$stock.txt" ~/Desktop/Stocks/"${rating%%-*}"/ fi 将替换为文件名,当读取该文件名时,将返回所包含命令的输出。因此,<(...)在父shell中运行foo < <(...),其stdin来自foo中的命令。请参阅BashFAQ #24以了解为什么这是必要的,而不是运行...
  • grep -e Rank "$stock.txt" | read _ _ _ rating _将其输入流的第四个字读入变量read _ _ _ rating _。 (第一个,第二个,第三个,第五个和第五个被读入名为rating的变量,这是你不关心/想要扔掉的东西的惯例。
  • _会在第一个"${rating%%-*}"之后抛弃变量rating中的所有内容,从而将-转换为1-Strong1转换为{ {1}}等等。

但是,以上所有内容并未解释您收到的确切错误。为此,让我们分解您的2-Buy命令:

2

...那么,串联在一起并传递给awk的字符串是什么(因此system("mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt") ; )?

system()

在这里查看问题?第四件(你打算和其他人连在一起)不是awk中的一个字符串!因此,当它包含/bin/sh次操作时,将其视为数字除法 - 将之前的内容转换为数值,然后除以其后的内容(同样转换为整数) 。在某些awk版本中,包括我的版本,这会导致零除错误;你的显然不同。

(另外,system( "mv " "'$stock'.txt" " " ~/Desktop/Stocks/1/"'$stock'.txt" ) ; 文字字符串,此处未用/替换,但这是一个单独的问题)

答案 1 :(得分:2)

您当前正在创建此执行树:

shell { awk { system( shell ) } }

不要这样做,它非常混乱且容易出错。这样做(或同样简单):

shell { awk }

e.g。这可能是您所需要的(取决于HD.txt的内容):

mv "${stock}.txt" ~/Desktop/Stocks/"$(awk '/Rank/{ sub(/-.*/,"",$4); print $4 }' "${stock}.txt")"

答案 2 :(得分:0)

你把事情弄得太复杂了1)坚持使用awk和2)在那些mv命令的目标路径中重复文件名。

我将假设&#34; Rank&#34; line有以空格分隔的列,第4个是包含你的id的列,正如你自己所假设的那样。 如果此假设或以下假设不成立,则此处的解决方案可能会给您带来问题。见查理的回答。

如果您确定第4个字段始终包含格式为digits-text的字符串,那么您可以尝试使用

#!/bin/bash

stock=HD

id=`cat "$stock.txt"|grep Rank| cut -d ' ' -f 4| sed 's@-.*@@g'`
echo "$stock.txt" ~/Desktop/Stocks/"$id"
#mv "$stock.txt" ~/Desktop/Stocks/"$id"

我已经注释掉了实际的mv命令。回声线将允许您仔细检查文件是否确实会到达正确的目的地。进行一些测试,如果事情看起来不错,请通过删除符号mv取消注释#行。

编辑:确保所有目录〜/ Desktop / Stocks / $ id在发出mv命令之前存在。否则你将丢失这些文件!,因为它们会相互覆盖,只有移动到任何给定〜/ Desktop / Stocks / $ id目录的最后一个文件的内容才能生存 - 但是命名$ ID !!

以下代码将确保将它们移动到目录中并且不会相互覆盖。

#!/bin/bash

stock=HD
DDIR=~/Desktop/Stocks

id=`cat "$stock.txt"|grep Rank| cut -d ' ' -f 4| sed 's@-.*@@g'`
echo "$stock.txt" ~/Desktop/Stocks/"$id"
{ [ -d "$DDIR/$id" ] || mkdir "$DDIR/$id" ;} &&  mv "$stock.txt" ~/Desktop/Stocks/"$id"

首先检查文件夹$ DDIR / $ id是否存在,如果它不存在则进行检查。只有这样才能继续实际行动。