将命令的输出结果存储到数组中

时间:2018-03-21 10:54:12

标签: bash

我的bash命令输出有问题。 我想将命令的结果保存到数组,并将第一部分切换为[0],将第二部分切割为[1]

result=$(findId PATTERN | tr -s " " | cut -d " " -f 1)

findID的输出是:

id errorcode nameOfProgramRunned

示例:

12345 "compilation problem" fullScan.java
12346 "other problem" basicTest.java

我想将id保存到array[0],将nameofProgramRunned保存到array[1]

主要问题是我想避免两次执行命令,因为结果可能不同。

当前代码:

#!/bin/sh
echo 'Enter error code:'
read errorLine

result=$(findID PATTERN | awk '{print $1}')

while read -r line
do

    dir="/proj/jobs/"$line"/screenlog.*"

    if [ -e $dir ]
    then
        if grep -qi "$errorLine" $dir  
        then    
            echo -e "\e[101m$line:\e[49m"       
            grep $dir -i -e "$errorLine"

        fi  
    fi
done <<<"$result"

我想将nameOfProgramRunned添加到最终的grep

我正在使用bash

4 个答案:

答案 0 :(得分:0)

针对开放式阵列编辑。

help read # bash built in help

请注意IFS设置为制表符分隔符

另外看看

func GetprofilesApi(c *gin.Context) {
var p Profile
profiles, err, count := p.GetProfiles()
if err != nil {
    log.Fatalln(err)
}

c.JSON(http.StatusOK, gin.H{
    "Number of Results": count,

    "profiles": profiles,
}) }

//Getprofiles() function
func (p *Profile) GetProfiles() (profiles []Profile, err error, count int) {
profiles = make([]Profile, 0)
rows, err := db.Query("SELECT id, firstname, lastname, email, username, phone, function  FROM profile")
defer rows.Close()

if err != nil {
    return
}
//counting rows

for rows.Next() {
    var profile Profile
    rows.Scan(&profile.ID, &profile.FirstName, &profile.LastName, &profile.Email, &profile.Username, &profile.Phone, &profile.Function)
    profiles = append(profiles, profile)
    count = count + 1
}
if err = rows.Err(); err != nil {
    return
}
return}

答案 1 :(得分:0)

您可以使用Perl正则表达式格式化输出并将其放入Bash中的关联数组中,但我不建议在Bash中使用数组。如果id字段是唯一的,则关联数组将起作用。

export errorLine='other problem'

# Simulating the command output
export result=$(cat <<EOF
12345 "compilation problem" fullScan.java
12346 "other problem" basicTest.java
64321 "other problem" basicTest2.java
EOF
)

# Replacing one doule quote by two double quote (escaping double quotes)
result=$(perl -e '($str = $ENV{result}) =~ s/"/""/g; print "$str";')

# Declaring an associative array
declare -A errorsArray

export paramID
export paramName

while read -r line
do
  export linePerl="${line}"

  # Prints the columns enclosed by double quotes, which is why I escaped double quotes before
  export regexEval=$(perl -e '
    if($ENV{linePerl} =~ m/^(.+?)\s+""$ENV{errorLine}""\s+?(.+)$/s) {
      print "\"$1\";\"$2\"";
    }
  ')

  # Checks if the line matches the pattern
  if [[ ! -z "${regexEval}" ]]
  then
    paramID=$(perl -e '$str = ($ENV{regexEval} =~ m/;?"(.+?[^"])";?/g)[0]; print "$str";')
    paramName=$(perl -e '$str = ($ENV{regexEval} =~ m/;?"(.+?[^"])";?/g)[1]; print "$str";')

    errorsArray["${paramID}"]="${paramName}"
  fi
done <<< "$result"

# Prints the associative array
for i in "${!errorsArray[@]}"
do
  echo "${i}: ${errorsArray[$i]}"
done

# Output:
#
# 12346: basicTest.java
# 64321: basicTest2.java
#

这是另一个解决方案,使用CSV文件而不是关联数组,我发现它更容易,更有效:

export errorLine='other problem'

# Simulating the command output
export result=$(cat <<EOF
12345 "compilation problem" fullScan.java
12346 "other problem" basicTest.java
64321 "other problem" basicTest2.java
EOF
)

# Using Perl regular expression to format the output to CSV format
perl -e '
($str = $ENV{result}) =~ s/"/""/g; # Replacing one doule quote by two double quote (escaping double quotes)

while($str =~ m/^(.+)\s+""$ENV{errorLine}""\s+(.+)$/mg) {
  print "\"$1\";\"$2\"\n";
}
' > output.csv

# Printing "output.csv" file
cat output.csv

# Output:
#
# "12346";"basicTest.java"
# "64321";"basicTest2.java"
#

while read -r line
do
  export linePerl="${line}"

  # Removing the double quotes and printing
  perl -e '
    @str = $ENV{linePerl} =~ m/;?"(.+?[^"])";?/g;
    print "@str[0]: @str[1]\n"
  '
done < output.csv

# Output:
#
# 12346: basicTest.java
# 64321: basicTest2.java
#

如果要在Perl的上下文中访问环境变量,请不要忘记使用export将Bash环境变量公开给Perl。

答案 2 :(得分:0)

如果您的环境足够安全并且可以信任您的输入,则还可以将行解析委托给Shell本身。像这样:

main () {
  findID \
  | while read line ; do
    eval "process_element $line"
    done
}

process_element () {
  local id problem program
  id="$1" ; problem="$2" ; program="$3"

  printf \
    "id: %s, problem: %s, program: %s\n" \
    "$id" \
    "$problem" \
    "$program"
  #do_your_things "$id" "$program"
}

findID () {
  echo '12345 "compilation problem" fullScan.java'
  echo '12346 "other problem" basicTest.java'
}

main

snippet on repl.it

答案 3 :(得分:0)

您可以拆分管道以同时处理所有列。

假设

  • findID输出由TAB标记,而不是“”,因此cut没问题
  • 您可以将输出数组保存到文件file1file2,...中,以便以后可以检索它们

然后您可以通过以下方式分隔列:

findId PATTERN   | tee >(cut -d$'\t' -f1 > file1) >(cut -d$'\t' -f2 > file2) >(cut -d$'\t' -f3 > file3)

我已经用以下最小示例测试了代码:

echo -e '12345\t"compilation problem"\tfullScan.java
12346\t"other problem"\tbasicTest.java'  | tee >(cut -d$'\t' -f1 > file1) >(cut -d$'\t' -f2 > file2) >(cut -d$'\t' -f3 > file3)

也就是说,管道被分成不同的管道,每列一个

感谢https://unix.stackexchange.com/questions/28503