根据条件

时间:2016-12-16 17:16:01

标签: linux bash shell csv awk

我有一个* .csv文件。价值如下

"ASDP02","8801942183589"

"ASDP06","8801939151023"

"CSDP04","8801963981740"

"ASDP09","8801946305047"

"ASDP12","8801941195677"

"ASDP05","8801922826186"

"CSDP08","8801983008938"

"ASDP04","8801944346555"

"CSDP11","8801910831518"

或有时值如下

"8801989353984","KSDP05" 

"8801957608165","ASDP11" 

"8801991455848","CSDP10" 

"8801981363116","CSDP07" 

"8801921247870","KSDP07" 

"8801965386240","CSDP06" 

"8801956293036","KSDP10" 

"8801984383904","KSDP11" 

"8801944211742","ASDP09" 

我只想把数值(例如8801989353984)放在第一列。是否可以使用BASH脚本?

5 个答案:

答案 0 :(得分:1)

Sed也是你的朋友

<强>输入

cat 41189347
"ASDP02","8801942183589"
"ASDP06","8801939151023"
"CSDP04","8801963981740"
"ASDP09","8801946305047"
"ASDP12","8801941195677"
"ASDP05","8801922826186"
"CSDP08","8801983008938"
"ASDP04","8801944346555"
"CSDP11","8801910831518"

<强>脚本

sed -E 's/^("[[:alpha:]]+.*"),("[[:digit:]]+")$/\2,\1/' 41189347

<强>输出

"8801942183589","ASDP02"
"8801939151023","ASDP06"
"8801963981740","CSDP04"
"8801946305047","ASDP09"
"8801941195677","ASDP12"
"8801922826186","ASDP05"
"8801983008938","CSDP08"
"8801944346555","ASDP04"
"8801910831518","CSDP11"

答案 1 :(得分:1)

awk救援!

$ awk -F, -v OFS=, '$1~/[A-Z]/{t=$2;$2=$1;$1=t}1' file

如果第一个字段有alpha字符,则交换第一列和第二列并打印。

答案 2 :(得分:0)

Bash可以完成工作,但awk可能是重新安排文件的更好选择:

sample.csv:

"ASDP02","8801942183589"
"8801944211742","ASDP09"

命令:

awk -F, 'BEGIN{OFS=","}{$1=$1;if(substr($1, 2, length($1) - 2) + 0 == substr($1, 2, length($1) - 2)){print $1,$2}else{print $2,$1}}' sample.csv
  • substr($1, 2, length($1) - 2) + 0 == substr($1, 2, length($1) - 2)检查列是否为数字。如果是,则打印原始行,否则切换column1和column2

输出:

"8801942183589","ASDP02"
"8801944211742","ASDP09"

答案 3 :(得分:0)

以下命令假定CSV文件中的单元格不包含换行符和逗号。否则,您应该使用Perl,PHP或其他能够正确解析CSV文件的编程语言编写更复杂的脚本。但是Bash肯定不适合这项任务。

<强>的Perl

perl -F, -nle '@F = reverse @F if $F[0] =~ /^"\d+"$/;
print join(",", @F)' file

小心,如果单元格包含换行符或逗号,请使用Perl的Text::CSV模块。虽然在Perl中这是一项简单的任务,但它超出了当前问题的范围。

该命令用逗号(-F,)分割输入行,并将结果存储到每行的@F数组中。如果第一个字段$F[0]与正则表达式匹配,则数组中的项目将反转。您也可以这样交换项目:($F[0], $F[1]) = ($F[1], $F[0])

最后,用逗号连接数组项,并将打印到标准输出

如果您要就地修改文件,请使用-i选项:perl -i.backup -F, ...

<强> AWK

awk -F, -vOFS=, '/^"[0-9]+",/ {print; next}
{ t = $1; $1 = $2; $2 = t; print }' file

输入和输出字段分隔符设置为, -F,-vOFS=,

如果该行符合模式/^"[0-9]+",/(该行以&#34;数字&#34; CSV列开头),脚本将打印记录并前进到next记录。否则执行下一个块。

在下一个块中,它交换前两列并将结果打印到标准输出

如果您想就地编辑文件,请参阅this question的答案。

答案 4 :(得分:0)

您可以创建纯bash脚本来生成具有所需结构的其他文件:

#!/bin/bash

csv_file="/path/to/your/csvfile"
output_file="/path/to/output_file"

#Optional
rm -rf "${output_file}"

readarray -t LINES < <(cat < "${csv_file}" 2> /dev/null)

for item in "${LINES[@]}"; do

  if [[ $item =~ ^\"([0-9A-Z]+)\"\,\"([0-9]+)\" ]]; then
    echo "\"${BASH_REMATCH[2]}\",\"${BASH_REMATCH[1]}\"" >> "${output_file}"
  else
    echo "$item" >> "${output_file}"
  fi
done

即使您的文件是“混合”,这也有效。我的意思是某些行格式正确,其他行格式不正确。