我的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
答案 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
答案 3 :(得分:0)
您可以拆分管道以同时处理所有列。
假设
findID
输出由TAB标记,而不是“”,因此cut
没问题file1
,file2
,...中,以便以后可以检索它们然后您可以通过以下方式分隔列:
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)
也就是说,管道被分成不同的管道,每列一个