Filter CSV rows where specific fields are null or non-null

I’m trying to filter lines in a CSV file based on two specific conditions, using awk:

  1. Field 2 should be null (empty) and Field 4 should be non-null (not empty).
  2. Field 2 should be non-null (not empty) and Field 4 should be null (empty).

For example, consider a CSV file with the following content:

"venBio","http://www.venbio.com","","venBio is a Investor located in United States, North America."
"zhenZhou","http://www.zhenzhou.com","",""
"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

I want the awk script to first print:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

followed by

"zhenZhou","http://www.zhenzhou.com","",""

I’ve tried various approaches, but I can’t seem to get the filtering right for these conditions. Could someone guide me on the proper awk syntax to achieve this?


Approaches tried:

awk -F, '($2 == "" && $4 != "")' input.csv

awk -F, '($2 != "" && $4 == "")' input.csv

awk -F, '($2 ~ /^[[:space:]]*$/ && $4 !~ /^[[:space:]]*$/)' input.csv

awk -F, '($2 !~ /^[[:space:]]*$/ && $4 ~ /^[[:space:]]*$/)' input.csv

4

You may use this awk:

awk -F, -v nul='""' '$2 != nul && $4 == nul {s = s $0 ORS}
$2 == nul && $4 != nul; END {printf "%s", s}' file

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

3

The One True Awk supports CSV directly but XOR still has to be implemented as NOT/AND/OR:

awk --csv '(!length($2)&&length($4)) || (length($2)&&!length($4))' input.csv

giving:

"zhenZhou","http://www.zhenzhou.com","",""
"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

If you really want the output in the order from the question, you can run the command twice:

awk --csv '!length($2)&&length($4)' input.csv
awk --csv 'length($2)&&!length($4)' input.csv

giving:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

Assumptions:

  • all fields are wrapped in double quotes
  • no fields include embedded/escaped double quotes

If we use -F'"' to designate the input field delimiter then we just need to remember that all data fields are actually even-numbered (ie, 1st field is referenced as $2, 2nd field is referenced as $4).

Modifying and combining OP’s 1st two awk scripts:

awk -F'"' '
FNR==NR { if ($4 == "" && $8 != "") print; next }    # process 1st file
        { if ($4 != "" && $8 == "") print       }    # process 2nd file
' input.csv input.csv

NOTES:

  • $4 is the 2nd data field; $8 is the 4th data field
  • print with no args is treated the same as print $0 (ie, print the entire line as is)
  • we provide two references of the input file (input.csv) in order to limit memory usage while generating the output in the desired order

This generates:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

The problem with the commands you tried is that awk is not ignoring the double quotes within each field. You can use the separator argument to solve that:

awk -F'","' '($2 == "" && $4 != """) || ($2 != "" && $4 == """)' file.csv

Because field $4 is the last one, you still need to account for that last double quote.

If you want to use a true csv parser (other than on GNU awk) you can use Ruby:

ruby -r csv -ne 'BEGIN{a=[]}
li=CSV.parse_line($_); a.unshift($_) if li[1].empty? ^ li[3].empty?
END{puts a.join }' f.csv

Prints:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

IIUC, for the latest GNU awk 5.3.0:

awk --csv '($2=="") != ($4=="")' file
#"zhenZhou","http://www.zhenzhou.com","",""
#"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

Note: this one only works when order does not matter.

To make desired order, another two-pass solution can be:

awk --csv '$(2+n) == "" && $(4-n) != ""' file n=2 file 
#"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
#"zhenZhou","http://www.zhenzhou.com","",""

so with the first pass, n="", we test against ($(2+0),$(4-0)) or ($2,$4), for the second pass n=2 and we test ($(2+2), $(4-2) which is ($4,$2).

This can also be written as $(lshift(2,n)) == "" && $(rshift(4,n)) != "" and use n=1 for the 2nd pass.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa

Filter CSV rows where specific fields are null or non-null

I’m trying to filter lines in a CSV file based on two specific conditions, using awk:

  1. Field 2 should be null (empty) and Field 4 should be non-null (not empty).
  2. Field 2 should be non-null (not empty) and Field 4 should be null (empty).

For example, consider a CSV file with the following content:

"venBio","http://www.venbio.com","","venBio is a Investor located in United States, North America."
"zhenZhou","http://www.zhenzhou.com","",""
"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

I want the awk script to first print:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

followed by

"zhenZhou","http://www.zhenzhou.com","",""

I’ve tried various approaches, but I can’t seem to get the filtering right for these conditions. Could someone guide me on the proper awk syntax to achieve this?


Approaches tried:

awk -F, '($2 == "" && $4 != "")' input.csv

awk -F, '($2 != "" && $4 == "")' input.csv

awk -F, '($2 ~ /^[[:space:]]*$/ && $4 !~ /^[[:space:]]*$/)' input.csv

awk -F, '($2 !~ /^[[:space:]]*$/ && $4 ~ /^[[:space:]]*$/)' input.csv

4

You may use this awk:

awk -F, -v nul='""' '$2 != nul && $4 == nul {s = s $0 ORS}
$2 == nul && $4 != nul; END {printf "%s", s}' file

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

3

The One True Awk supports CSV directly but XOR still has to be implemented as NOT/AND/OR:

awk --csv '(!length($2)&&length($4)) || (length($2)&&!length($4))' input.csv

giving:

"zhenZhou","http://www.zhenzhou.com","",""
"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

If you really want the output in the order from the question, you can run the command twice:

awk --csv '!length($2)&&length($4)' input.csv
awk --csv 'length($2)&&!length($4)' input.csv

giving:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

Assumptions:

  • all fields are wrapped in double quotes
  • no fields include embedded/escaped double quotes

If we use -F'"' to designate the input field delimiter then we just need to remember that all data fields are actually even-numbered (ie, 1st field is referenced as $2, 2nd field is referenced as $4).

Modifying and combining OP’s 1st two awk scripts:

awk -F'"' '
FNR==NR { if ($4 == "" && $8 != "") print; next }    # process 1st file
        { if ($4 != "" && $8 == "") print       }    # process 2nd file
' input.csv input.csv

NOTES:

  • $4 is the 2nd data field; $8 is the 4th data field
  • print with no args is treated the same as print $0 (ie, print the entire line as is)
  • we provide two references of the input file (input.csv) in order to limit memory usage while generating the output in the desired order

This generates:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

The problem with the commands you tried is that awk is not ignoring the double quotes within each field. You can use the separator argument to solve that:

awk -F'","' '($2 == "" && $4 != """) || ($2 != "" && $4 == """)' file.csv

Because field $4 is the last one, you still need to account for that last double quote.

If you want to use a true csv parser (other than on GNU awk) you can use Ruby:

ruby -r csv -ne 'BEGIN{a=[]}
li=CSV.parse_line($_); a.unshift($_) if li[1].empty? ^ li[3].empty?
END{puts a.join }' f.csv

Prints:

"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
"zhenZhou","http://www.zhenzhou.com","",""

IIUC, for the latest GNU awk 5.3.0:

awk --csv '($2=="") != ($4=="")' file
#"zhenZhou","http://www.zhenzhou.com","",""
#"Loren","","","A famous Hollywood actress from the 1950s and 1960s"

Note: this one only works when order does not matter.

To make desired order, another two-pass solution can be:

awk --csv '$(2+n) == "" && $(4-n) != ""' file n=2 file 
#"Loren","","","A famous Hollywood actress from the 1950s and 1960s"
#"zhenZhou","http://www.zhenzhou.com","",""

so with the first pass, n="", we test against ($(2+0),$(4-0)) or ($2,$4), for the second pass n=2 and we test ($(2+2), $(4-2) which is ($4,$2).

This can also be written as $(lshift(2,n)) == "" && $(rshift(4,n)) != "" and use n=1 for the 2nd pass.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật