我正在从CSV
文件中导入一些数据,以及大于1000
变成的数字1,100
等。
从中删除引号和逗号以便我可以将其放入int
字段的好方法是什么?
编辑:
数据实际上已经在 MySQL 表中,所以我需要能够使用 SQL。很抱歉混淆了。
我的猜测是,因为数据能够导入该字段实际上是 varchar 或某些字符字段,因为导入数字字段可能会失败。这是一个测试用例,我只运行了一个 MySQL、SQL 解决方案。
该表只是一个单列 (alpha),它是一个 varchar。
mysql> desc t;
+-------+-------------+------+-----+---------+-------+
| Field | Type | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| alpha | varchar(15) | YES | | NULL | |
+-------+-------------+------+-----+---------+-------+
添加记录
mysql> insert into t values('"1,000,000"');
Query OK, 1 row affected (0.00 sec)
mysql> select * from t;
+-------------+
| alpha |
+-------------+
| "1,000,000" |
+-------------+
更新声明。
mysql> update t set alpha = replace( replace(alpha, ',', ''), '"', '' );
Query OK, 1 row affected (0.00 sec)
Rows matched: 1 Changed: 1 Warnings: 0
mysql> select * from t;
+---------+
| alpha |
+---------+
| 1000000 |
+---------+
所以最后我使用的语句是:
UPDATE table
SET field_name = replace( replace(field_name, ',', ''), '"', '' );
我查看了MySQL 文档,看起来我无法执行正则表达式 find和 replace。尽管您可以像Eldila一样使用正则表达式进行查找,然后使用替代解决方案进行替换。
还要小心,s/"(\d+),(\d+)"/$1$2/
因为如果数字多于一个逗号,例如“1,000,000”,您将要进行全局替换(在 perl 中是s///g
)。但即使使用全局替换,替换也会从您上次停止的地方开始(除非 perl 不同),并且会错过所有其他逗号分隔的组。一个可能的解决方案是使第一个 (\d+) 像这样可选s/(\d+)?,(\d+)/$1$2/g
,在这种情况下,我需要第二个查找和替换来去除引号。
这里有一些正则表达式仅作用于字符串“1,000,000”的 ruby 示例,请注意字符串中没有双引号,这只是数字本身的字符串。
>> "1,000,000".sub( /(\d+),(\d+)/, '\1\2' )
# => "1000,000"
>> "1,000,000".gsub( /(\d+),(\d+)/, '\1\2' )
# => "1000,000"
>> "1,000,000".gsub( /(\d+)?,(\d+)/, '\1\2' )
# => "1000000"
>> "1,000,000".gsub( /[,"]/, '' )
# => "1000000"
>> "1,000,000".gsub( /[^0-9]/, '' )
# => "1000000"
这是正则表达式的一个很好的例子。您可以在导入之前(更容易)或稍后在 SQL 导入接受这些字符时(几乎不那么容易)对数据运行查找和替换。但无论哪种情况,您都可以使用多种方法进行查找和替换,无论是编辑器、脚本语言、GUI 程序等。请记住,您将要查找和替换所有坏字符。
查找逗号和引号(假设只有双引号)的典型正则表达式是:(黑名单)
/[,"]/
或者,如果您发现将来可能会发生变化,则此正则表达式会匹配除数字或小数点以外的任何内容。(白名单)
/[^0-9\.]/
上面的人讨论的是,我们并不知道您的 CSV 文件中的所有数据。听起来您想从 CSV 文件中的所有数字中删除逗号和引号。但是因为我们不知道 CSV 文件中还有什么,所以我们要确保我们不会损坏其他数据。只是盲目地进行查找/替换可能会影响文件的其他部分。
你可以使用这个 perl 命令。
Perl -lne 's/[,|"]//; print' file.txt > newfile.txt
您可能需要稍微尝试一下,但它应该可以解决问题。
我的命令确实删除了所有 ',' 和 '"'。
为了更严格地转换 sting "1,000",您将需要以下命令。
Perl -lne 's/"(\d+),(\d+)"/$1$2/; print' file.txt > newfile.txt
实际上,nlucaroni,您的情况不太正确。你的例子不包括双引号,所以
id,age,name,...
1,23,phil,
不会匹配我的正则表达式。它需要格式“XXX,XXX”。我想不出什么时候会不正确匹配的例子。
以下所有示例都不会在正则表达式中包含分隔符:
"111,111",234 234,"111,111" "111,111","111,111"
如果您能想到一个反例,请告诉我。
干杯!
更改后的问题的解决方案基本相同。
您必须使用正则表达式 where 子句运行选择查询。
类似的东西
Select *
FROM SOMETABLE
WHERE SOMEFIELD REGEXP '"(\d+),(\d+)"'
对于这些行中的每一行,您希望执行以下正则表达式替换 s/"(\d+),(\d+)"/$1$2/ 然后使用新值更新字段。
请 Joseph Pecoraro 认真并在对任何文件或数据库进行大规模更改之前进行备份。因为每当您执行正则表达式时,如果您遗漏了某些情况,您可能会严重混淆数据。
Daniel 和 Eldila 的回答有一个问题:他们删除了整个文件中的所有引号和逗号。
当我必须做这样的事情时,我通常会首先用制表符替换所有分隔引号和(通常)分号。
因为我知道我的受影响值将在哪一列中,所以我再进行一次搜索和替换:
...给定带逗号的值在第三列中。
您需要以“^”开头,以确保它从行首开始。然后,您重复 ([0-9]+)\t 的频率,因为您只想按原样保留列。
([0-9]+),([0-9]+) 搜索有一个数字,然后是逗号,然后是另一个数字的值。
在替换字符串中,我们使用 \1 和 \2 来保留编辑行中的值,用 \t(制表符)分隔它们。然后我们把 \3\4 (中间没有制表符)放在数字的两个组成部分,不带逗号。之后的所有值都将保持不变。
如果您需要文件使用分号来分隔元素,则可以继续并用分号替换选项卡。但是,如果您省略引号,则必须确保文本值本身不包含任何分号。这就是为什么我更喜欢使用 TAB 作为列分隔符。
我通常在支持 RegExp 的普通文本编辑器 (EditPlus) 中执行此操作,但相同的 regexp 可用于任何编程语言。