当前位置: 首页 > 知识库问答 >
问题:

使用awk或其他方法替换文件中的整个字段值

储国发
2023-03-14

我有一个从postgresql表导出多个字段,包括布尔值(由postgresql导出为tf字符),我需要将其导入到另一个数据库(monetdb),该数据库不理解t/f为bool值。

(编辑删除空格以反映真实的文件方面,避免愤怒的评论-以前有空格显示)

id|val_str|bool_1|bool2|bool_3|bool4|
1|help|t|t|f|t|
2|test|f|t|f|f|
...

由于我不能替换所有出现的t/f,我需要在我的模式中集成字段分隔符。我尝试使用awkt字段替换为TRUE,将f字段替换为FALSE

awk -F'|' '{gsub(/\|t\|/, "|TRUE|"); gsub(/\|f\|/, "|FALSE|"); print;}' 

这部分起作用,因为具有相同值的连续字段(|t | t |)将只替换第一个匹配项(| TRUE | t |——第二个匹配项实际上是t |)。

id|val_str|bool_1|bool2|bool_3|bool4|
1|help|TRUE|t|FALSE|TRUE|
2|test|FALSE|TRUE|FALSE|f|
...

表有~450列,所以我不能真正指定要替换的列列表,也不能在postgres中“转换”布尔列(我可以但是...)。

我可以运行两次gsub(),但我正在寻找更优雅的方法来匹配所有字段的整个字段内容。

gsub(/^t$/,...)也没有帮助,因为我们大部分时间都在一行中间。

共有3个答案

陈扬
2023-03-14

如果perl是好的,你可以使用lookaround:

$ cat ip.txt 
id |  val_str  | bool_1 | bool2  | bool_3 | bool4  | 
1  |    help   |   t    |   t    |   f    |   t    |
2  |    test   |   f    |   t    |   f    |   f    | 

$ perl -pe 's/\|\K\h*t\h*(?=\|)/  TRUE  /g; s/\|\K\h*f\h*(?=\|)/  FALSE /g' ip.txt 
id |  val_str  | bool_1 | bool2  | bool_3 | bool4  | 
1  |    help   |  TRUE  |  TRUE  |  FALSE |  TRUE  |
2  |    test   |  FALSE |  TRUE  |  FALSE |  FALSE | 
  • \\\\K正查找以匹配\\code>


也可以将循环与sed一起使用。在GNU sed 4.2上测试。2,语法可能因其他实现而有所不同

$ sed ':a s/| *t *|/|  TRUE  |/;ta; :b s/| *f *|/|  FALSE |/;tb' ip.txt 
id |  val_str  | bool_1 | bool2  | bool_3 | bool4  | 
1  |    help   |  TRUE  |  TRUE  |  FALSE |  TRUE  |
2  |    test   |  FALSE |  TRUE  |  FALSE |  FALSE | 
  • :一个标签


输入中没有空格

perl -pe 's/\|\Kt(?=\|)/TRUE/g; s/\|\Kf(?=\|)/FALSE/g' ip.txt 
sed ':a s/|t|/|TRUE|/;ta; :b s/|f|/|FALSE|/;tb' ip.txt 
awk 'BEGIN{FS=OFS="|"} {for(i=1;i<=NF;i++){if($i=="t"){$i="TRUE"} if($i=="f"){$i="FALSE"}} print}' ip.txt

彭嘉赐
2023-03-14

假设(根据您的评论)您的输入文件实际上看起来不像您发布的示例,而是像这样:

$ cat file
id|val_str|bool_1|bool2|bool_3|bool4|
1|help|t|t|f|t|
2|test|f|t|f|f|

那么你所需要的就是:

$ awk '{while(gsub(/\|t\|/,"|TRUE|")); while(gsub(/\|f\|/,"|FALSE|"));}1' file
id|val_str|bool_1|bool2|bool_3|bool4|
1|help|TRUE|TRUE|FALSE|TRUE|
2|test|FALSE|TRUE|FALSE|FALSE|

N个替换字符串的一般解决方案为:

$ awk 'BEGIN{m["f"]="FALSE"; m["t"]="TRUE"} {for (k in m) while(gsub("\\|"k"\\|","|"m[k]"|"));} 1' file
id|val_str|bool_1|bool2|bool_3|bool4|
1|help|TRUE|TRUE|FALSE|TRUE|
2|test|FALSE|TRUE|FALSE|FALSE|
连坚白
2023-03-14

表有~450列,所以我不能真正指定要替换的列列表,也不能在postgres中“转换”布尔列(我可以但是...)。

你可以让Postgres为你做这项工作。生成SELECT列表的基本查询:

SELECT string_agg(CASE WHEN atttypid = 'bool'::regtype
                       THEN quote_ident(attname) || '::text'
                       ELSE quote_ident(attname) END, ', ' ORDER BY attnum)
FROM   pg_attribute
WHERE  attrelid = 'mytable'::regclass  -- provide table name here
AND    attnum > 0
AND    NOT attisdropped;

生成以下格式的字符串:

col1, "CoL 2", bool1::text, "Bool 2"::text

所有标识符都被正确转义。列按默认顺序排列。复制并执行它。使用COPY导出到文件。(或psql中的\copy)性能与导出普通表大致相同。如果不需要大写,请省略upper()

为什么对文本进行简单的强制转换就足够了?

  • 返回布尔值为真或假选择(PostgreSQL/pgAdmin)

关于regclass和转义标识符正确:

  • 表名作为PostgreSQL函数参数

如果您需要一个完整的语句,大写为TRUE/FALSE/NULL,标准SQL转换符号(没有冒号::),仍然是原始列名也许还有一个模式限定的表名:

SELECT 'SELECT '
     || string_agg(CASE WHEN atttypid = 'bool'::regtype
                        THEN format('upper(cast(%1$I AS text)) AS %1$I', attname)
                        ELSE quote_ident(attname) END, ', ' ORDER BY attnum)
     || ' FROM myschema.mytable;'           -- provide table name twice now
FROM   pg_attribute
WHERE  attrelid = 'myschema.mytable'::regclass
AND    attnum > 0
AND    NOT attisdropped;

生成表单的完整语句:

SELECT col1, "CoL 2", upper(cast(bool1 AS text) AS bool1, upper(cast("Bool 2" AS text)) AS "Bool 2" FROM myschema.mytable;

 类似资料:
  • 问题内容: 我正在尝试用多个其他单词替换字符串中的多个单词。字符串是“我有一只猫,一只狗和一只山羊”。 但是,它不会产生“我有一只狗,一只山羊和一只猫”,而是会产生“我有一只猫,一只猫和一只猫”。在JavaScript中是否可以同时用多个其他字符串替换多个字符串,以便产生正确的结果? 问题答案: 具体解决方案 您可以使用一个函数替换每个函数。 概括它 如果您要动态维护正则表达式并仅将将来的交换添加

  • 我正在尝试用多个其他单词替换字符串中的多个单词。绳子是“我有一只猫,一只狗,和一只山羊。” 然而,这并不产生“我有一只狗,一只山羊,一只猫”,而是产生“我有一只猫,一只猫,一只猫”。是否可以在JavaScript中同时用多个其他字符串替换多个字符串,从而产生正确的结果?

  • 代码示例: 我发现了许多类似的问题(比如“替换Apache POI XWPF中的文本”),但没有找到我的问题的答案(这里的答案“Apache POI XWPFRun对象中的分离文本行”提供了不方便的解决方案)。 我尝试使用docx4j,这个示例=>“docx4j find and replace”,但是docx4j的工作原理与此相似。 ,那个模板位于不同的xml标记中,我不明白为什么... 请帮助

  • 本文向大家介绍Angular2整合其他插件的方法,包括了Angular2整合其他插件的方法的使用技巧和注意事项,需要的朋友参考一下 前言:现在有很多朋友在接触Angular2的时候,总是不可避免的会使用一些其他的第3方的插件,而这些插件可能都是基于jQuery的,而且也没有对应的angular2的版本,这里我就来讲解一下,在这种情况下,如何整合第3方的jQuery插件。我们以Angular2整合z

  • 问题内容: 我正在Linux上工作。我有2个文件-file1.dat和file2.dat。 对于file2: 我想用file2.dat的前3行替换file1.dat的前4行。所以我的输出如下 我尝试了以下输入: 但是使用此输入,我有以下输出: 我应该如何修改输入命令?我尝试了各种组合。 问题答案: 是你的朋友 脚本 输出量 提示 NR-已处理的记录总数 FNR-处理的记录总数,但在读取新文件时会重

  • 我想在文本文件中用新的英文字符替换突厥语字符{code>{c',c',I',I',G',G',S',S}。 这是我的密码。我在控制台上只获得原始内容,没有任何更改,也不会创建新文件。 编辑: 这是适用于我的新代码。但是我想使用一个较短的代码来替换方法。