bash/awk/unix 检测 csv 文件行的变化
bash/awk/unix detect changes in lines of csv files
我有这种格式的时间戳:
(normal_file.csv)
timestamp
19/02/2002
19/02/2002
19/02/2002
19/02/2002
19/02/2002
19/02/2002
日期通常是统一的,但是,有些文件具有不规则的日期模式,例如此示例:
(abnormal_file.csv)
timestamp
19/02/2002
19/02/2003
19/02/2005
19/02/2006
在我的目录中,有数百个由 normal.csv 和 abnormal.csv 组成的文件。
我想编写一个 bash 或 awk 脚本来检测目录中所有文件的日期模式。带有 abnormal.csv 的文件应该自动移动到一个新的单独目录(比如 dir_different/)。
目前,我尝试了以下方法:
#!/bin/bash
mkdir dir_different
for FILE in *.csv;
do
# pipe 1: detect the changes in the line
# pipe 2: print the timestamp column (first column, columns are comma-separated)
awk ' != prev {print ; prev = }' < $FILE | awk -F , '{print }'
done
如果给定文件中的时间戳是正常的,那么只会打印一个时间戳;但对于异常文件,会打印多个日期。
不知道怎么把异常文件和正常文件区分开来,试过如下:
do
output=$(awk 'FNR==3{print [=14=]}' $FILE)
echo ${output}
if [[ ${output} =~ ([[:space:]]) ]]
then
mv $FILE dir_different/
fi
done
或者是否有更简单的方法来检测行中的变化并分离具有不同行的文件?感谢您的任何建议:)
假设您的“正常”CSV 文件中有 none 个尾随换行符,这应该可以很好地进行分隔:
#!/bin/bash
mkdir -p dir_different
for FILE in *.csv;
do
if awk '{a[]++}END{if(length(a)<=2){exit 1}}' "$FILE" ; then
echo mv "$FILE" dir_different
fi
done
在 dry-run 之后,只需删除 echo
:)
编辑:
{a[]++}
该位创建一个数组 a,它获取每行的第一个字段作为索引,并且每次看到相同的值时都会递增。
END{if(length(a)<=2){exit 1}}
这将检查数组中有多少个元素。如果少于 3 个(如果总是有相同的日期并且我们只得到 1 header,1 个日期应该是这种情况)以 1.
退出处理
"$FILE"
是 bash 脚本的一部分,而不是 awk,我出于习惯引用了你的变量,如果你的文件名中有空格,你就会明白为什么: )
所以,“normal”文件只包含两个不同的行:
timestamp
dd/mm/yyyy
测试一个文件是否正常就这么简单:
[ $(sort -u file.csv | wc -l) -eq 2 ]
这导致以下可能的解决方案:
#!/usr/bin/env bash
mkdir -p dir_different
for FILE in *.csv;
do
if [ $(sort -u "$FILE" | wc -l) -ne 2 ] ; then
echo mv "$FILE" dir_different
fi
done
我有这种格式的时间戳:
(normal_file.csv)
timestamp
19/02/2002
19/02/2002
19/02/2002
19/02/2002
19/02/2002
19/02/2002
日期通常是统一的,但是,有些文件具有不规则的日期模式,例如此示例:
(abnormal_file.csv)
timestamp
19/02/2002
19/02/2003
19/02/2005
19/02/2006
在我的目录中,有数百个由 normal.csv 和 abnormal.csv 组成的文件。
我想编写一个 bash 或 awk 脚本来检测目录中所有文件的日期模式。带有 abnormal.csv 的文件应该自动移动到一个新的单独目录(比如 dir_different/)。
目前,我尝试了以下方法:
#!/bin/bash
mkdir dir_different
for FILE in *.csv;
do
# pipe 1: detect the changes in the line
# pipe 2: print the timestamp column (first column, columns are comma-separated)
awk ' != prev {print ; prev = }' < $FILE | awk -F , '{print }'
done
如果给定文件中的时间戳是正常的,那么只会打印一个时间戳;但对于异常文件,会打印多个日期。
不知道怎么把异常文件和正常文件区分开来,试过如下:
do
output=$(awk 'FNR==3{print [=14=]}' $FILE)
echo ${output}
if [[ ${output} =~ ([[:space:]]) ]]
then
mv $FILE dir_different/
fi
done
或者是否有更简单的方法来检测行中的变化并分离具有不同行的文件?感谢您的任何建议:)
假设您的“正常”CSV 文件中有 none 个尾随换行符,这应该可以很好地进行分隔:
#!/bin/bash
mkdir -p dir_different
for FILE in *.csv;
do
if awk '{a[]++}END{if(length(a)<=2){exit 1}}' "$FILE" ; then
echo mv "$FILE" dir_different
fi
done
在 dry-run 之后,只需删除 echo
:)
编辑:
{a[]++}
该位创建一个数组 a,它获取每行的第一个字段作为索引,并且每次看到相同的值时都会递增。
END{if(length(a)<=2){exit 1}}
这将检查数组中有多少个元素。如果少于 3 个(如果总是有相同的日期并且我们只得到 1 header,1 个日期应该是这种情况)以 1.
"$FILE"
是 bash 脚本的一部分,而不是 awk,我出于习惯引用了你的变量,如果你的文件名中有空格,你就会明白为什么: )
所以,“normal”文件只包含两个不同的行:
timestamp
dd/mm/yyyy
测试一个文件是否正常就这么简单:
[ $(sort -u file.csv | wc -l) -eq 2 ]
这导致以下可能的解决方案:
#!/usr/bin/env bash
mkdir -p dir_different
for FILE in *.csv;
do
if [ $(sort -u "$FILE" | wc -l) -ne 2 ] ; then
echo mv "$FILE" dir_different
fi
done