每次从多个文件中找到特定字符时,流式传输一个行

每次从多个文件中找到特定字符时,流式传输一个行

这是我尝试在一行中转换的文件示例:

-
Jun 6th
something2
09:00
some text blah blah
something1
Jun 6th
something1
09:00
some text xxx
something1

我试图将这些行作为一行,例如 csv,示例:

Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

答案1

你可以试试这个 SED 一句话:

sed -ne '/^–/{g; /./!b; s/\n//; s/\n/, /g; p; z; h; b}; H' INPUTFILE

解释:

/^–/{                 -->  if line starts with char "–", then:
    g                 -->      copy hold space to pattern space
    /./!b             -->      empty line? restart cycle
    s/\n//            -->      get rid of first newline
    s/\n/, /g         -->      replace all other newlines by ", "
    p                 -->      print pattern space
    z                 -->      erase pattern space
    h                 -->      erase hold space
    b                 -->      start new cycle
    }
H                     -->  otherwise, append newline + pattern space to hold space

输入:


Jun 6th
something2
09:00
some text blah blah
some other thing2
Jun 7th
something1
10:30
some text xxx
some other thing1
Jun 9th
something3
12:15
some text yyy
some other thing3
Jun 8th
something4
07:05
some text zzz
some other thing4

输出:

Jun 6th, something2, 09:00, some text blah blah, some other thing2
Jun 7th, something1, 10:30, some text xxx, some other thing1
Jun 9th, something3, 12:15, some text yyy, some other thing3
Jun 8th, something4, 07:05, some text zzz, some other thing4

希望有帮助。

答案2

首先,需要注意的是,您的数据使用两种不同类型的破折号字符进行分隔:ASCII 连字符以及 Unicode 破折号 (U+2013)。

Awk 的 GNU 实现 (GNU Awk) 可以处理用于记录分离的正则表达式。这是一句:

$ gawk -v RS='\n?[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1
Jun 6th, something1, 09:00, some text xxx, something1

data包含您的示例的文件在哪里,逐字保存。

我们设置了一个记录分隔符正则表达式,它匹配一个可选的换行符,后跟一个 ASCII 破折号或 Unicode 破折号,后跟一个换行符。那么这些记录中的字段分隔符就是换行符。输出分隔符是逗号和空格。

该表达式$1=$1有两个目的。将字段分配回自身会导致记录$0被重构,同时考虑到自定义OFS字段分隔符。那么我们只需打印它即可。由于数据以记录分隔符开头,因此有一个初始空白记录。对于该记录,表达式$1 = $1分配空白值,并且由于这是结果,因此表达式是布尔值 false;该记录不会被打印。

如果我们不在模式\n中包含可选的前导RS,那么每个记录都会以一个额外的空白字段结束,因为后面的换行符something1会被解释为字段分隔符。我们需要最后一个字段后面的换行符作为记录分隔的一部分。它必须是可选的,因为文件以记录分隔符开头,前面没有换行符。没有它我们会得到这个:

$ gawk -v RS='[–-]\n' -v FS='\n' -v OFS=', ' '$1 = $1' data
Jun 6th, something2, 09:00, some text blah blah, something1,
Jun 6th, something1, 09:00, some text xxx, something1,

额外的逗号,由于额外的空字段。

答案3

您可以使用 tr 和 sed 命令来做到这一点:

$ tr '\n' ',' <input_file | sed 's/-,/\n/g' | sed 's/.$//'

Jun 6th,something2,09:00,some text blah blah,something1
Jun 6th,something1,09:00,some text xxx,something1

(第二个 sed 去掉了尾随的逗号)

您需要确保输入文件中的虚线分隔符相同。当我复制它们来测试这段代码时,它们不是。

答案4

something*假设您想要有效的 CSV 输出,输入中可以有引号或逗号,记录的 、等部分中不能有换行符,some text*并且只有真正的-记录分隔符,这里有一个输入文件,可以测试潜在的解决方案:

$ cat file
-
Jun 6th
something2
09:00
"some "text" blah blah"
"something1"
-
Jun 6th
something1
09:00
some, text, xxx
something1
-

这是使用任何 POSIX awk 的解决方案,其输出是有效的 CSV:

$ cat tst.awk
$1 == "-" {
    if ( NR > 1 ) {
        print ""
    }
    sep = ""
    next
}
/[",]/ {
    gsub(/^"|"$/,"")
    gsub(/"/,"\"\"")
    $0 = "\"" $0 "\""
}
{
    printf "%s%s", sep, $0
    sep = ","
}

$ awk -f tst.awk file
Jun 6th,something2,09:00,"some ""text"" blah blah","something1"
Jun 6th,something1,09:00,"some, text, xxx",something1

如果这不是您想要给定输入的输出,请编辑问题中的示例以显示如何处理输入中带有,s 和s 的情况。"

相关内容