在Bash中使用转义字符填充特定列

时间:2017-02-02 10:45:27

标签: bash unix awk sed grep

我有一个由数据行组成的文件,其中列由给定的分隔符指定。

e.g。

20170202,ABC,USD,USD,100,20170202
20170202,ABC,GBP,USD,200,20170202
20170201,ABC,NOK,USD,300,20170204
20170131,ABC,DKK,USD,400,20170202

我想要一种打印此文件行的方法,例如,第1列是20170202,第4列是USD。同时,我想用打印输出字符包围打印输出中的那些列,以便向用户突出显示它们。

因此,在上面的示例中,只应打印第1行和第2行,并且:

  • 第1列(但不是第6列)应突出显示
  • 第4栏(但不是第3栏)应突出显示

目前我为每个传递的参数都有一个链式grep。

e.g。

cat myfile.txt | grep -w "20170202" | grep -w "USD"

然后将其传送到sed语句,该语句将20170202和USD用转义字符填充以对输出进行着色。

但是,在上面的示例中,第4行将失败,因为它将被错误地输出,第4列和第6列突出显示。对于第1行也是如此,第1,3,4和6列将突出显示(当我只想要1和4时)。

任何人都可以建议如何为任意选择的列进行此操作吗?

包括awk,因为我想这个解决方案可能涉及它。

4 个答案:

答案 0 :(得分:1)

awk 中,您可以将字段替换为彩色字段。下面的脚本应该 做好工作

# cat 42000109
1. 20170202,ABC,USD,USD,100,20170202
2. 20170202,ABC,GBP,USD,200,20170202
3. 20170201,ABC,NOK,USD,300,20170204
4. 20170131,ABC,DKK,USD,400,20170202

# awk -v FS=" |," '$2=="20170202" && $4=="USD"{$2="\033[1;31m"$2"\033[1;39m";$4="\033[1;31m"$4"\033[1;39m";print}' 42000109

1. 20170202 ABC USD USD 100 20170202
#fields 2 and 4 will be highlighted

有关bash颜色的更多提示,请查看[ this ]链接。

修改

如果开头的数字不存在,那么下面的内容应该

# awk -v FS=',' -v OFS=',' '$1=="20170202" && $4=="USD"{$1="\033[1;31m"$1"\033[1;39m";$4="\033[1;31m"$4"\033[1;39m";print}' 42000109
20170202,ABC,USD,USD,100,20170202
20170202,ABC,GBP,USD,200,20170202
# #fields 1 and 4 will be highlighted

答案 1 :(得分:1)

考虑首先构建您想要的颜色的地图,然后使用它,例如:

$ cat tst.awk
BEGIN {
    n = split("\
        red     31 \
        green   32 \
        reset   39 \
            ", tmpA)
    for (i=1; i<=n; i+=2) {
        colors[tmpA[i]] = ("\033[1;" tmpA[i+1] "m")
    }
    FS=OFS=","
}

function color(field,clr) {
    $field = (colors[clr] $field colors["reset"])
}

($1=="20170202") && ($4=="USD") {
    color(1,"red")
    color(4,"green")
}

{ print }

$ awk -f tst.awk file | cat -v
^[[1;31m20170202^[[1;39m,ABC,USD,^[[1;32mUSD^[[1;39m,100,20170202
^[[1;31m20170202^[[1;39m,ABC,GBP,^[[1;32mUSD^[[1;39m,200,20170202
20170201,ABC,NOK,USD,300,20170204
20170131,ABC,DKK,USD,400,20170202

答案 2 :(得分:0)

使用 sed (有点难以阅读所有\

sed -e '/^\(20170202\)\(,\([^,]*,\)\{3\}\)\(USD\)\(,.*\)/!d' -e 's//\\\1\\\2\\\4\\\5/' YourFile

# OR into a more generic form
sed -e '/^\('${YourDate}'\)\(,\([^,]*,\)\{3\}\)\('${YourCurrency}'\)\(,.*\)/!d' -e 's//\\\1\\\2\\\4\\\5/' YourFile

awk 版本

awk '$1=="20170202"&&$4=="USD"{$1="\\"$1"\\";$4="\\"$4"\\";print}' FS=',' OFS=',' YourFile

相同,更通用,带注释(使用变量进行批处理)

awk -v MyDate="{YourDate}" -v MyCur="${YourCurrency} '
   # Parameter assign some variable with external value of script

   # if first field (col) = the date AND 4th field = Currency
   $1 == MyDate && $4 == MyCur {
      # replace field 1 by itself surrounded by escape char
      $1 = "\\" $1 "\\"
      # same for field 4
      $4 = "\\" $4 "\\"

      # Print line (with new content)
      # default output is modified by OFS value adapted (default is space separator between field and set to , in this script)
      print 
      }
   # assign 2 varible (FS and OFS for field separator as input and output)
   # before reading first availble file (YourFile)
   ' FS=',' OFS=',' YourFile

答案 3 :(得分:-2)

cat text file| awk -F "," '$1 ~ /20170202/ && $3 == "USD"  { print }'

awk接受当前文件的分隔符逗号“,”并将它们分开,可以通过$ 1,$ 2,$ 3等访问它们。所以我们可以根据需要尝试查看匹配是否为1美元和3美元。 $ 1匹配是通过正则表达式匹配完成的,该匹配通过运算符~完成,正则表达式字符串保留为正斜杠/