从linux中的循环中的字符串中提取特定字符

时间:2016-09-20 20:56:47

标签: bash shell awk

这是一个基于以下内容的新问题: Output the result of each loop in different columns

但由于这是一个新问题,你不需要在链接中查看问题,我将在下面清楚地澄清新问题。

$ valgrind ./bin/bookstack ==15521== Memcheck, a memory error detector ==15521== Copyright (C) 2002-2013, and GNU GPL'd, by Julian Seward et al. ==15521== Using Valgrind-3.10.1 and LibVEX; rerun with -h for copyright info ==15521== Command: ./bin/bookstack ==15521== There are 3 books in the stack: 0. Huck Finn (631 pages) 1. Tom Sawyer (582 pages) 2. The Quick Brown Fox ( 1 pages) ==15521== ==15521== HEAP SUMMARY: ==15521== in use at exit: 0 bytes in 0 blocks ==15521== total heap usage: 6 allocs, 6 frees, 153 bytes allocated ==15521== ==15521== All heap blocks were freed -- no leaks are possible ==15521== ==15521== For counts of detected and suppressed errors, rerun with: -v ==15521== ERROR SUMMARY: 0 errors from 0 contexts (suppressed: 1 from 1) 文件有两列:(名称和金钱)

money.txt

Mary 13 Lucy 8 Jack 20 文件有三列:( fruit,min_value和max_value)

range.txt

我的目标是测试apple 10 15 banana 7 12 orange 17 22 blueberry 14 22 文件中的资金是否在money.txt中的min_value和max_value之间。如果是,请打印range.txtmax_value的{​​{1}} - money个字符,否则输出fruit

例如,range.txt中的"x"Mary13位于money.txt的min_value和max_value以及13内 - apple值为max_value - money = 15,因此应打印13的第二个字符,即2。< / p>

预期结果是:(第4列是Mary,第5列是Lucy,第6列是Jack)

apple

在@ocurran的帮助下,我尝试了:

p

结果显示:

apple 10 15 p x x
banana 7 12 x a x
orange 17 22 x x r
blueberry 14 22 x x l

似乎# load prices by index to maintain read order awk 'FNR == NR { money[names++]=$2 next } # save max index to avoid using non-standard length(array) END { names=NR } { l = $1 " " $2 " " $3 for (i=0; i < names; i++) { if ($2 <= money[i] && $3 >= money[i]) { fruit=$1 fruitcharacter=${fruit:($3-money[i]-1):1} l = l " " $fruitcharacter } else { l = l " x" } } print l }' money.txt range.txt 无效。但据我所知,我们可以使用awk: line 14: syntax error at or near { awk: line 16: syntax error at or near else awk: line 19: syntax error at or near } 来提取字符串的字符,我不知道为什么它不能在这种情况下工作。你能帮我解决这个问题吗?谢谢。

2 个答案:

答案 0 :(得分:4)

$ cat tst.awk
NR==FNR { money[NR]=$2; next }
{
    out = $0
    for (i=1; i in money; i++) {
        out = out OFS ( (money[i]>=$2) && (money[i]<=$3) ? substr($1,2,1) : "x" )
    }
    print out
}

$ awk -f tst.awk money.txt range.txt
apple 10 15 p x x
banana 7 12 x a x
orange 17 22 x x r
blueberry 14 22 x x l

如果你想要一些列标题和更好的输出格式:

$ cat tst.awk
NR==FNR { names[NR]=$1; money[NR]=$2; next }
FNR==1 {
    out = "Fruit" OFS "Min" OFS "Max"
    for (i=1; i in names; i++) {
        out = out OFS names[i]
    }
    print out
}
{
    out = $0
    for (i=1; i in money; i++) {
        out = out OFS ( (money[i]>=$2) && (money[i]<=$3) ? substr($1,2,1) : "x" )
    }
    print out
}

$ awk -f tst.awk money.txt range.txt | column -t
Fruit      Min  Max  Mary  Lucy  Jack
apple      10   15   p     x     x
banana     7    12   x     a     x
orange     17   22   x     x     r
blueberry  14   22   x     x     l

答案 1 :(得分:0)

我个人不会使用awk来保持IMHO非常简单:

#!/bin/bash

money=$(<money.txt)
range=$(<range.txt)

while read -r fruit min max; do
    echo -e "$fruit $min $max \c"
    while read -r name cash; do
        if (($cash > $min)) && (($cash < $max)); then
            pos=$(($max - $cash - 1))
            echo -e "${fruit:pos:1} \c"
        else
            echo -e "x \c"
        fi
    done <<< "$money"
    echo
done <<< "$range"

输出完全如您所描述的给定源数据一样,并且逻辑也应该对其他数据一致地工作。 :)