用键分隔行并存储在不同的文件中
Separate lines with keys and store in different files
如何在一个文本文件中分离(获取)整行十六进制数字key相关的整行和DEBUG整行,然后存储在不同的文件中,其中key是这样的格式:“[uid key]” ?
即忽略任何非 DEBUG 的行。
in.txt:
[ uid 28fd4583833] DEBUG web.Action
[ uid 39fd5697944] DEBUG test.Action
[ uid 56866969445] DEBUG test2.Action
[ uid 76696944556] INFO test4.Action
[ uid 39fd5697944] DEBUG test7.Action
[ uid 85483e10256] DEBUG testing.Action
输出文件命名为“out”+ i +“.txt”,其中 i = 1、2、3、4。
即
out1.txt:
[ uid 28fd4583833] DEBUG web.Action
out2.txt:
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
out3.txt:
[ uid 56866969445] DEBUG test2.Action
out4.txt:
[ uid 85483e10256] DEBUG testing.Action
我试过了:
awk 'match([=15=], /uid ([^]]+)/, a) && /DEBUG/ {print > (a[1] ".txt")}' in.txt
第一个解决方案: 使用 GNU awk
尝试遵循单个 awk
代码。我在哪里使用 GNU awk
.
的 PROCINFO["sorted_in"]
方法
awk '
BEGIN{
PROCINFO["sorted_in"] = "@ind_num_asc"
}
!/DEBUG/{ next }
match([=10=],/uid [a-zA-Z0-9]+/){
ind=substr([=10=],RSTART,RLENGTH)
arr[ind]=(arr[ind]?arr[ind] ORS:"") [=10=]
}
END{
for(i in arr){
outputFile=("out"++count".txt")
print arr[i] > (outputFile)
close(outputFile)
}
}
' Input_file
第二个解决方案: 与任何 awk
,请使用您显示的示例尝试以下解决方案。在此处将 Input_file
名称更改为您的实际文件名。在此处使用带有选项 -s
的 GNU sort
在对值进行排序时保持顺序。
awk '
!/DEBUG/{ next }
match([=11=],/uid [0-9a-zA-Z]+/){
print substr([=11=],RSTART,RLENGTH)";"[=11=]
}' Input_file |
sort -sk2n |
cut -d';' -f2- |
awk '
match([=11=],/uid [0-9a-zA-Z]+/){
if(prev!=substr([=11=],RSTART,RLENGTH)){
count++
close(outputFile)
}
outputFile="out"count".txt"
print > (outputFile)
prev=substr([=11=],RSTART,RLENGTH)
}
'
第一个解决方案的解释:为第一个解决方案添加详细解释:
awk ' ##Starting awk program from here.
BEGIN{ ##Starting BEGIN section from here.
PROCINFO["sorted_in"] = "@ind_num_asc" ##Setting PROCINFO["sorted_in"] to @ind_num_asc to sort any array with index.
}
!/DEBUG/{ next } ##If a line does not contain DEBUG then jump to next line.
match([=12=],/uid [a-zA-Z0-9]+/){ ##using match function to match uid space and alphanumeric values here.
ind=substr([=12=],RSTART,RLENGTH) ##Creating ind which contains sub string of matched sub string in match function.
arr[ind]=(arr[ind]?arr[ind] ORS:"") [=12=] ##Creating array arr with index of ind and keep adding current line value to same index.
}
END{ ##Starting END block of this program from here.
for(i in arr){ ##Traversing through array arr here.
outputFile=("out"++count".txt") ##Creating output file name here as per OP requirement.
print arr[i] > (outputFile) ##printing current array element into outputFile variable.
close(outputFile) ##Closing output file in backend to avoid too many files opened error.
}
}
' Input_file ##Mentioning Input_file name here.
如果您愿意更改输出文件名以包含密钥(坦率地说,这似乎比名称中的 one-up 计数器更有用),您可以这样做:
awk '/DEBUG/{print > ("out-" ".txt")}' FS='[][ ]*' in.txt
这会将所有匹配字符串 DEBUG
和关键字 85483e10256
的行放入文件 out-85483e10256.txt
等
如果您确实想保留 one-up 计数器,您可以这样做:
awk '/DEBUG/{if( ! a[] ) a[] = ++counter;
print > ("out" a[] ".txt")}' FS='[][ ]*' in.txt
基本上,想法是使用正则表达式 [][ ]*
作为字段分隔符,匹配方括号或 space 的字符串。这样,</code> 是初始 <code>[
之前的文本,</code> 是字符串 <code>uid
,而
是密钥。这将(应该!)正确地获取可能具有略微不同的白色 space 的行的密钥。我们使用关联数组来跟踪哪些键已经被看到以跟踪计数器。但是在输出文件名中使用密钥确实更干净。
如果您的文件格式与您显示的一致,您可以这样做:
awk '
!="DEBUG" { next }
!f[] { f[]=++i }
{ print > ("out" f[] ".txt") }
' in.txt
对 -s
使用 GNU 排序(以保证保留每个键值的输入行顺序)和任何 awk:
$ sort -sk3,3 in.txt |
awk '!="DEBUG"{next} !=prev{close(out); out="out"(++i)".txt"; prev=} {print > out}'
$ head out*.txt
==> out1.txt <==
[ uid 28fd4583833] DEBUG web.Action
==> out2.txt <==
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
==> out3.txt <==
[ uid 56866969445] DEBUG test2.Action
==> out5.txt <==
[ uid 85483e10256] DEBUG testing.Action
如果您没有 GNU 排序,那么您可以使用任何排序应用 DSU (Decorate/Sort/Undecorate) 习语:
$ awk -v OFS='\t' '{print NR, [=12=]}' in.txt | sort -k4,4 -k1,1n | cut -f2- |
awk '!="DEBUG"{next} !=prev{close(out); out="out"(++i)".txt"; prev=} {print > out}'
请注意,上面只有 sort
必须处理内存中的所有输入,并且它旨在使用请求分页等来处理大量输入,而 awk 仅处理 1 行一次并且几乎不在内存中保留任何内容,并且一次只打开 1 个输出文件,因此对于大文件,上述方法比在 awk 中存储大量内存或同时打开许多输出文件的方法更有可能成功.
一个相对便携的基于 awk
的解决方案,具有这些亮点 ::
- 输出行不截断前缘 double space
- 输出文件名遵循稳定的输入行顺序,无需 pre-sort 行、post-sort 行或利用
gnu gawk
特定功能
- 测试并确认正在处理
gawk 5.1.1
,包括-ce
标志,
mawk 1.3.4
,
mawk 1.9.9.6
,以及
macOS nawk 20200816
————————————————————————————————
# gawk profile, created Thu May 19 12:10:56 2022
BEGIN {
____ = "test_72297811_" # opt. filename prefix
OFS = FS = "^ [[] uid "
_+=_ = gsub("\^|[[][]]", _, OFS)
_*= _--
} NF *= / DEBUG / {
print >> (__[___ = substr($NF,_~_,_)] ?__[___]:\
__[___]= ____ "out" length(__) ".txt" )
} END {
for (_ in __) { close(__[_]) } }'
————————————————————————————————
==> test_72297811_out1.txt <==
[ uid 28fd4583833] DEBUG web.Action
==> test_72297811_out2.txt <==
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
==> test_72297811_out3.txt <==
[ uid 56866969445] DEBUG test2.Action
==> test_72297811_out4.txt <==
[ uid 85483e10256] DEBUG testing.Action
如何在一个文本文件中分离(获取)整行十六进制数字key相关的整行和DEBUG整行,然后存储在不同的文件中,其中key是这样的格式:“[uid key]” ? 即忽略任何非 DEBUG 的行。
in.txt:
[ uid 28fd4583833] DEBUG web.Action
[ uid 39fd5697944] DEBUG test.Action
[ uid 56866969445] DEBUG test2.Action
[ uid 76696944556] INFO test4.Action
[ uid 39fd5697944] DEBUG test7.Action
[ uid 85483e10256] DEBUG testing.Action
输出文件命名为“out”+ i +“.txt”,其中 i = 1、2、3、4。 即
out1.txt:
[ uid 28fd4583833] DEBUG web.Action
out2.txt:
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
out3.txt:
[ uid 56866969445] DEBUG test2.Action
out4.txt:
[ uid 85483e10256] DEBUG testing.Action
我试过了:
awk 'match([=15=], /uid ([^]]+)/, a) && /DEBUG/ {print > (a[1] ".txt")}' in.txt
第一个解决方案: 使用 GNU awk
尝试遵循单个 awk
代码。我在哪里使用 GNU awk
.
PROCINFO["sorted_in"]
方法
awk '
BEGIN{
PROCINFO["sorted_in"] = "@ind_num_asc"
}
!/DEBUG/{ next }
match([=10=],/uid [a-zA-Z0-9]+/){
ind=substr([=10=],RSTART,RLENGTH)
arr[ind]=(arr[ind]?arr[ind] ORS:"") [=10=]
}
END{
for(i in arr){
outputFile=("out"++count".txt")
print arr[i] > (outputFile)
close(outputFile)
}
}
' Input_file
第二个解决方案: 与任何 awk
,请使用您显示的示例尝试以下解决方案。在此处将 Input_file
名称更改为您的实际文件名。在此处使用带有选项 -s
的 GNU sort
在对值进行排序时保持顺序。
awk '
!/DEBUG/{ next }
match([=11=],/uid [0-9a-zA-Z]+/){
print substr([=11=],RSTART,RLENGTH)";"[=11=]
}' Input_file |
sort -sk2n |
cut -d';' -f2- |
awk '
match([=11=],/uid [0-9a-zA-Z]+/){
if(prev!=substr([=11=],RSTART,RLENGTH)){
count++
close(outputFile)
}
outputFile="out"count".txt"
print > (outputFile)
prev=substr([=11=],RSTART,RLENGTH)
}
'
第一个解决方案的解释:为第一个解决方案添加详细解释:
awk ' ##Starting awk program from here.
BEGIN{ ##Starting BEGIN section from here.
PROCINFO["sorted_in"] = "@ind_num_asc" ##Setting PROCINFO["sorted_in"] to @ind_num_asc to sort any array with index.
}
!/DEBUG/{ next } ##If a line does not contain DEBUG then jump to next line.
match([=12=],/uid [a-zA-Z0-9]+/){ ##using match function to match uid space and alphanumeric values here.
ind=substr([=12=],RSTART,RLENGTH) ##Creating ind which contains sub string of matched sub string in match function.
arr[ind]=(arr[ind]?arr[ind] ORS:"") [=12=] ##Creating array arr with index of ind and keep adding current line value to same index.
}
END{ ##Starting END block of this program from here.
for(i in arr){ ##Traversing through array arr here.
outputFile=("out"++count".txt") ##Creating output file name here as per OP requirement.
print arr[i] > (outputFile) ##printing current array element into outputFile variable.
close(outputFile) ##Closing output file in backend to avoid too many files opened error.
}
}
' Input_file ##Mentioning Input_file name here.
如果您愿意更改输出文件名以包含密钥(坦率地说,这似乎比名称中的 one-up 计数器更有用),您可以这样做:
awk '/DEBUG/{print > ("out-" ".txt")}' FS='[][ ]*' in.txt
这会将所有匹配字符串 DEBUG
和关键字 85483e10256
的行放入文件 out-85483e10256.txt
等
如果您确实想保留 one-up 计数器,您可以这样做:
awk '/DEBUG/{if( ! a[] ) a[] = ++counter;
print > ("out" a[] ".txt")}' FS='[][ ]*' in.txt
基本上,想法是使用正则表达式 [][ ]*
作为字段分隔符,匹配方括号或 space 的字符串。这样,</code> 是初始 <code>[
之前的文本,</code> 是字符串 <code>uid
,而 是密钥。这将(应该!)正确地获取可能具有略微不同的白色 space 的行的密钥。我们使用关联数组来跟踪哪些键已经被看到以跟踪计数器。但是在输出文件名中使用密钥确实更干净。
如果您的文件格式与您显示的一致,您可以这样做:
awk '
!="DEBUG" { next }
!f[] { f[]=++i }
{ print > ("out" f[] ".txt") }
' in.txt
对 -s
使用 GNU 排序(以保证保留每个键值的输入行顺序)和任何 awk:
$ sort -sk3,3 in.txt |
awk '!="DEBUG"{next} !=prev{close(out); out="out"(++i)".txt"; prev=} {print > out}'
$ head out*.txt
==> out1.txt <==
[ uid 28fd4583833] DEBUG web.Action
==> out2.txt <==
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
==> out3.txt <==
[ uid 56866969445] DEBUG test2.Action
==> out5.txt <==
[ uid 85483e10256] DEBUG testing.Action
如果您没有 GNU 排序,那么您可以使用任何排序应用 DSU (Decorate/Sort/Undecorate) 习语:
$ awk -v OFS='\t' '{print NR, [=12=]}' in.txt | sort -k4,4 -k1,1n | cut -f2- |
awk '!="DEBUG"{next} !=prev{close(out); out="out"(++i)".txt"; prev=} {print > out}'
请注意,上面只有 sort
必须处理内存中的所有输入,并且它旨在使用请求分页等来处理大量输入,而 awk 仅处理 1 行一次并且几乎不在内存中保留任何内容,并且一次只打开 1 个输出文件,因此对于大文件,上述方法比在 awk 中存储大量内存或同时打开许多输出文件的方法更有可能成功.
一个相对便携的基于 awk
的解决方案,具有这些亮点 ::
- 输出行不截断前缘 double space
- 输出文件名遵循稳定的输入行顺序,无需 pre-sort 行、post-sort 行或利用
gnu gawk
特定功能 - 测试并确认正在处理
gawk 5.1.1
,包括-ce
标志,mawk 1.3.4
,mawk 1.9.9.6
,以及macOS nawk 20200816
————————————————————————————————
# gawk profile, created Thu May 19 12:10:56 2022
BEGIN {
____ = "test_72297811_" # opt. filename prefix
OFS = FS = "^ [[] uid "
_+=_ = gsub("\^|[[][]]", _, OFS)
_*= _--
} NF *= / DEBUG / {
print >> (__[___ = substr($NF,_~_,_)] ?__[___]:\
__[___]= ____ "out" length(__) ".txt" )
} END {
for (_ in __) { close(__[_]) } }'
————————————————————————————————
==> test_72297811_out1.txt <==
[ uid 28fd4583833] DEBUG web.Action
==> test_72297811_out2.txt <==
[ uid 39fd5697944] DEBUG test.Action
[ uid 39fd5697944] DEBUG test7.Action
==> test_72297811_out3.txt <==
[ uid 56866969445] DEBUG test2.Action
==> test_72297811_out4.txt <==
[ uid 85483e10256] DEBUG testing.Action