使用 sed/awk 从重复行中删除模式
Use sed/awk to remove pattern from repeating lines
我在文件中有以下模式
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
我希望理想的输出是:
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
但是,我会接受:
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
我试过
的变体
sed 's/\(FILE1A\).*//'
但我一直得到与输入相同的结果。对于我哪里出错的任何指示,我将不胜感激。
谢谢。
这是否解决了您的问题?
cat test.txt
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
sed -n 's/\(.*)\).*\.\(.*\))/\t/p' test.txt
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
解释:
-n
选项 - 不打印所有内容
\(.*)\)
第一个捕获组 - 包括第一个“)”在内的所有内容
\.\(.*\))
第二个捕获组 - “.”之间的所有内容最后一个“)”
\t/p
打印第一个捕获组,然后是制表符,然后是第二个捕获组
sed 's/MYFILE[[:digit:]]\{0,\}\.//' file.txt
输出
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
sed 's/DEST.\{1,\}\.//;s/)$//' file.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
我将按如下方式利用 GNU AWK
来完成此任务,让 file.txt
内容成为
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
然后
awk 'BEGIN{FS="DEST\([[:alpha:][:digit:]]*\.|\)[[:space:]]*$"}{print }' file.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
说明:我将字段分隔符 (FS
) 设置为包含两个选项的值(由 |
剪切)
DEST(
零个或多个字母数字点 (.
)
)
后跟零个或多个空格(您的文件有尾随
空格) 和行尾 ($
)
由于 (
和 )
以及 .
具有特殊含义,我需要将它们转义以获得文字 (
和文字 )
以及文字 .
我需要的。我 print
值第 1 列的内容(即 TREE(
...)
和尾随空格)与第 2 列的值 FILE1A
连接,依此类推。
(在 gawk 4.2.1 中测试)
使用awk
你可以得到两个结果:
使用gsub()
函数的第一个输出:
awk '{gsub(/^[^.]+.|)$/,"",)} 1' file | column -tc2
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
或 sub()
的第二个输出:
awk '{sub(/MYFILE[[:digit:]]*./,"",)} 1' file | column -tc2
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
并使用 column -tc2
您可以保留(或调整)列之间的间距。
您还可以使用更具体的模式,并使用 negated character class 匹配除左括号和右括号之间的括号之外的任何字符。
(
捕获 组 1
\([^()]*\)[[:blank:]][[:blank:]]*
匹配从第一个开始 (
到结束 )
和后面的空格或制表符
)
关闭组 1
[^()]*
可选择匹配除 (
和 )
之外的任何字符
\(
匹配第二个左括号
[^()]*\.
匹配除 (
和 )
之外的任何字符,然后匹配一个点
([^()]*)
捕获 组 2 中除 (
和 )
之外的任何字符
\)
匹配第二个右括号
查看捕获组的 regex demo。
sed -n 's/\(([^()]*)[[:blank:]][[:blank:]]*\)[^()]*([^()]*\.\([^()]*\))//p' test.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
如果数据的格式始终与示例数据中的一样,使用 gnu awk,您还可以捕获第二个字段的右括号之前的最后一个字母数字字符,并使用制表符作为输出字段分隔符。
awk -v OFS='\t' '
match(, /([[:alnum:]]+)\)/, a){print , a[1]}
' test.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
我在文件中有以下模式
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
我希望理想的输出是:
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
但是,我会接受:
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
我试过
的变体sed 's/\(FILE1A\).*//'
但我一直得到与输入相同的结果。对于我哪里出错的任何指示,我将不胜感激。
谢谢。
这是否解决了您的问题?
cat test.txt
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
sed -n 's/\(.*)\).*\.\(.*\))/\t/p' test.txt
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
解释:
-n
选项 - 不打印所有内容
\(.*)\)
第一个捕获组 - 包括第一个“)”在内的所有内容
\.\(.*\))
第二个捕获组 - “.”之间的所有内容最后一个“)”
\t/p
打印第一个捕获组,然后是制表符,然后是第二个捕获组
sed 's/MYFILE[[:digit:]]\{0,\}\.//' file.txt
输出
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
sed 's/DEST.\{1,\}\.//;s/)$//' file.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
我将按如下方式利用 GNU AWK
来完成此任务,让 file.txt
内容成为
TREE(abc/x73/APPLE) DEST(MYFILE.FILE1A)
TREE(abc/x74/APPLE) DEST(MYFILE88.FILE1A)
TREE(abc/x100/APPLE) DEST(MYFILE100.FILE1B)
TREE(abc/x61/APPLE) DEST(MYFILE1000.FILE1A)
然后
awk 'BEGIN{FS="DEST\([[:alpha:][:digit:]]*\.|\)[[:space:]]*$"}{print }' file.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
说明:我将字段分隔符 (FS
) 设置为包含两个选项的值(由 |
剪切)
DEST(
零个或多个字母数字点 (.
))
后跟零个或多个空格(您的文件有尾随 空格) 和行尾 ($
)
由于 (
和 )
以及 .
具有特殊含义,我需要将它们转义以获得文字 (
和文字 )
以及文字 .
我需要的。我 print
值第 1 列的内容(即 TREE(
...)
和尾随空格)与第 2 列的值 FILE1A
连接,依此类推。
(在 gawk 4.2.1 中测试)
使用awk
你可以得到两个结果:
使用gsub()
函数的第一个输出:
awk '{gsub(/^[^.]+.|)$/,"",)} 1' file | column -tc2
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
或 sub()
的第二个输出:
awk '{sub(/MYFILE[[:digit:]]*./,"",)} 1' file | column -tc2
TREE(abc/x73/APPLE) DEST(FILE1A)
TREE(abc/x74/APPLE) DEST(FILE1A)
TREE(abc/x100/APPLE) DEST(FILE1B)
TREE(abc/x61/APPLE) DEST(FILE1A)
并使用 column -tc2
您可以保留(或调整)列之间的间距。
您还可以使用更具体的模式,并使用 negated character class 匹配除左括号和右括号之间的括号之外的任何字符。
(
捕获 组 1\([^()]*\)[[:blank:]][[:blank:]]*
匹配从第一个开始(
到结束)
和后面的空格或制表符
)
关闭组 1[^()]*
可选择匹配除(
和)
之外的任何字符
\(
匹配第二个左括号[^()]*\.
匹配除(
和)
之外的任何字符,然后匹配一个点([^()]*)
捕获 组 2 中除 \)
匹配第二个右括号
(
和 )
之外的任何字符
查看捕获组的 regex demo。
sed -n 's/\(([^()]*)[[:blank:]][[:blank:]]*\)[^()]*([^()]*\.\([^()]*\))//p' test.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A
如果数据的格式始终与示例数据中的一样,使用 gnu awk,您还可以捕获第二个字段的右括号之前的最后一个字母数字字符,并使用制表符作为输出字段分隔符。
awk -v OFS='\t' '
match(, /([[:alnum:]]+)\)/, a){print , a[1]}
' test.txt
输出
TREE(abc/x73/APPLE) FILE1A
TREE(abc/x74/APPLE) FILE1A
TREE(abc/x100/APPLE) FILE1B
TREE(abc/x61/APPLE) FILE1A