在AWK中找不到匹配项时显示消息

时间:2017-12-14 14:47:03

标签: bash csv awk

我正在编写一个小的BASH脚本,该脚本读取带有名称的csv文件,并提示用户输入要删除的名称。 csv文件如下所示:

Smith,John
Jackie,Jackson

要从列表中删除的人的名字和姓氏保存在bash变量$first_name$last_name.

这是我到目前为止所做的:

cat file.csv | awk -F',' -v last="$last_name" -v first="$first_name" ' ($1 != last || $2 != first) { print } ' > tmpfile1

这很好用。但是,即使没有员工匹配该名称,它仍会输出到tmpfile1。我想要的是:

if ($1 != last || $2 != first) { print }  > tmpfile1 ; else { print "No Match Found." }

我是awk的新手,无法让最后一部分工作。

注意:我不想使用像grep -v "$last_name,$first_name"这样的东西;我想使用过滤功能。

3 个答案:

答案 0 :(得分:1)

您可以直接在awk脚本中重定向,只输出找到的匹配项。

awk -F',' -v last="$last_name" -v first="$first_name" '
  $1==last && $2==first {next}
  {print > "tmpfile"}
' file.csv

以下是您的脚本与此之间的一些差异....

  • 这是直接读取您的CSV,而不是UUOC
  • 这主动跳过您要跳过的记录
  • 并通过重定向打印其他所有内容。

请注意,如果需要,您可以使用-v指定要在传入的变量中重定向的目标。

如果你真的想要“找不到匹配”错误,你可以设置一个标志,然后在awk中使用END特殊条件......

awk -F',' -v last="$last_name" -v first="$first_name" '
  $1==last && $2==first { found=1; next }
  { print > "tmpfile" }
  END { if (!found) print "No match found." > "/dev/stderr" }
' file.csv

如果你不希望在没有找到匹配的情况下创建tmpfile,你需要扫描文件TWICE,一次验证是否匹配,一次打印,或者是否没有风险文件的大小对于可用内存来说太大了,你可以保留一个缓冲区:

awk -F',' -v last="$last_name" -v first="$first_name" '
  $1==last && $2==first { next }
  { output = (output ? output ORS : "" ) $0 }
  END {
    if (output)
      print output > "tmpfile"
    else
      print "No match found." > "/dev/stderr"
  }
' file.csv

免责声明:我没有测试任何这些。 :)

答案 1 :(得分:0)

您可以对文件执行两次传递,或者您可以将所有文件排到目前为止在内存中排队,如果到达没有匹配的END块,则会失败。

#include <iostream>
#include <cstdlib>

using namespace std;

class student{
string name;
double ID;
int age;
string course;

public:
void setName(string sname);
void setID(double sID);
void setAge(int sage);
void setcourse(string scourse);

string getName();
double getID();
int getage();
string getcourse();
}

void student::setName(string sname){

name = sname;

}

void student::setID(double sID){

ID = sID;

}

void student::setAge(int sage){

age = sage;

}

void student::setcourse(string scourse){

course = scourse;
}

string student::getName(){

return name;
}

double student::getID(){

return ID;

}

int student::getage(){


return age;
}

string student::getcourse(){


return course;
}


void ReadData(student data[], int n);

int main() 
{
    student *record;
    int nItems;
    int i;


    cout << "How many students are there to process? : ";
    cin >> nItems;
    record = new student[nItems]; 
    ReadData(record, nItems);        

    for (i=0;i<nItems;i++)
        student i; 
        cout << record[i].name << "  " << record[i].ID << " " record[i].age << " " record[i].course << endl;
    return 0;
}

s


void ReadData(student data[], int n) {
    int i;
    for (i=0;i<n;i++) {
        cout << "Enter a name : ";
        cin  >> data[i].name;
        cout << "Enter a ID as double : ";
        cin >> data[i].ID;
        cout << "Enter age as integer :"
        cin >> data[i].age;
        cout << "Enter course as string :";
        cin >> data[i].course;


    }
}

这要求您有足够的内存来存储整个文件(当没有匹配时这将是必需的。)

答案 2 :(得分:0)

使用bash脚本,您可以测试awk是否打印出来。

如果是,请删除tmp文件。

c=$(awk -F',' -v a="$last_name" -v b="$first_name" '
  $1==a && $2==b {c=1;next}
  {print > "tmpfile"}
  END{if (!c){print "no match"}}' infile)
[ -n "$c" ] && { echo "$c"; rm tmpfile;}