我使用buildroot包将一些软件包移植到某些Linux嵌入式系统。某些软件包还会生成纯文本脚本和/或库控制文件,并引用暂存目录。在打包软件以供分发时,必须删除对暂存目录的引用。我没有问题使用SED删除这些引用。但是,这个处理留下了一些不希望的重复字符串模式,我摘录如下所示。我想知道是否可以使用SED来删除这些重复项。
注1 : ' dependency_libs =' 被排除在外,现在进行了修改,如下所示。我试图简洁地摘录这里需要的东西,但没有包括' dependency_libs ='之前因为它不包含任何重复项。显然,它在下面的一些建议的解决方案中起着重要作用。因此,我在这里为后人修改了它。
Note2 :我刚从@potong发现 sed 脚本的一个小错误。如果重复的字符串是最后一个没有空格的对象,则 sed 脚本将失败。在这种情况下,第一个' dependency_libs =' 行将部分失败 sed 脚本。第二个' dependency_libs =' 行在行尾(在单引号之前)包含一个空格,并且没有问题地通过 sed 脚本。我在这里修改了它以显示差异。
cppflags=-I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine
cxxflags=-I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine
Cflags: -I/usr/include -I/include -I/usr/include -I/include -I${includedir}/mine
Libs: -L/usr/lib -L/lib -L/usr/lib -L/lib -L${libdir} -lmine${suffix}
dependency_libs='-L/usr/lib -L/lib -L/usr/lib -L/lib -L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib -L/usr/lib -L/lib -L/usr/lib -L/lib'
dependency_libs='-L/usr/lib -L/lib -L/usr/lib -L/lib -L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib -L/usr/lib -L/lib -L/usr/lib -L/lib '
这样它就会变成:
cppflags=-I/usr/include -I/include -I${includedir}/mine
cxxflags=-I/usr/include -I/include -I${includedir}/mine
Cflags: -I/usr/include -I/include -I${includedir}/mine
Libs: -L/usr/lib -L/lib -L${libdir} -lmine${suffix}
dependency_libs='-L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib'
dependency_libs='-L/usr/lib/libiconv-full/lib -L/usr/lib/libintl-full/lib'
答案 0 :(得分:1)
这可能适合你(GNU sed):
sed -r ':a;s|((-[IL]/\S+\s).*)\2|\1|;ta' file
这将查找以-I/
或-L/
开头的字符串,后跟一个或多个非空格和重复的空格,并删除第二次出现。如果发生替换,则重复该过程,直到不再发生替换为止。
答案 1 :(得分:0)
这可能对您有用:
awk -F- '
{
for(i = 2; i <= NF; ++i) a[$i] = 1;
printf("%s", $1)
for(x in a) printf("-%s ", x)
print""
delete a
}
'
输出:
cppflags=-I${includedir}/mine -I/include -I/usr/include
cxxflags=-I${includedir}/mine -I/include -I/usr/include
Cflags: -I${includedir}/mine -I/include -I/usr/include
Libs: -L${libdir} -lmine${suffix} -L/lib -L/usr/lib
请注意,它不会保留目录的顺序,并且会在此处添加额外的空间。
如果您需要保留目录的顺序,并且可以使用gawk
,请尝试:
gawk -F- '
BEGIN {PROCINFO["sorted_in"] = "@val_num_asc"}
{
for(i = 2; i <= NF; ++i)
if (!($i in a))
a[$i] = i;
printf("%s", $1)
for(x in a) printf("-%s ", x)
print""
delete a
}
'
输出:
cppflags=-I/usr/include -I/include -I${includedir}/mine
cxxflags=-I/usr/include -I/include -I${includedir}/mine
Cflags: -I/usr/include -I/include -I${includedir}/mine
Libs: -L/usr/lib -L/lib -L${libdir} -lmine${suffix}
或者你可以使用像这样的非gnu awk获得相同的输出:
awk -F- '
{
for(i = 2; i <= NF; ++i)
if (!($i in a))
a[$i] = i;
printf("%s", $1)
for(x in a) b[a[x]] = x
for(x in b) printf("-%s ", b[x])
print""
delete a
delete b
}
'
当然,如果你需要摆脱额外的空间,你可以通过tr -s ' '
管道输出。
答案 2 :(得分:0)
我不认为sed
会起作用,因为您需要一个 field 定向的实用程序,它可以处理单行的相互关联的部分。
awk
中bash
的使用是一种选择,但这是纯#!/usr/bin/env bash
while read -r line; do
# Split line into prefix, separator, options array.
[[ $line =~ ^([^=:]+)([:=]\ *)(.*)$ ]]
prefix=${BASH_REMATCH[1]}
sep=${BASH_REMATCH[2]}
read -ra optArray <<<"${BASH_REMATCH[3]}"
# Loop over options array and build up a list without duplicates.
dedupOptList=''
for opt in "${optArray[@]}"; do
[[ " $dedupOptList " == *" $opt "* ]] || dedupOptList+=" $opt"
done
# Finally, rebuild the line with the deduplicated options list and print.
printf '%s%s%s\n' "$prefix" "$sep" "${dedupOptList:1}"
done < file
解决方案。
注意:
{{1}}