我有一个这样的字符串:
myString='value1|value57|value31|value21'
我发了一个名为values_to_remove.txt的文件,其中包含一个值列表,每行一个
values_to_remove.txt
value1
value31
在bash中,如何删除" values_to_remove.txt"中包含的值?从字符串开始,考虑到值是由管道分隔的,当然如果我删除了一个值,我必须删除前面和后面的管道(如果有的话)。
我已经在python中实现了这个并且从bash调用了python脚本,但是我需要使用一行命令直接在bash中执行此操作,而不是使用小脚本,否则我已经可以使用我的小python脚本了。
这是python代码
myString = 'value1|value2|value3|value4'
arrString = myString.split("|")
with open("myfile.txt", encoding="utf-8") as file:
for l in file:
if l in arrString:
arrString.remove(l)
myNewString = "|".join(arrString)
请注意:由pipe分隔的值可以是任何字符串。
谢谢
答案 0 :(得分:3)
您可以使用此awk
:
awk -v str="$myString" 'BEGIN {
n = split(str, a, /\|/)
}
{
val[$1]
}
END {
for (i=1; i<=n; i++)
if (!(a[i] in val))
s = (s == "" ? "" : s "|") a[i]
print s
}' values_to_remove.txt
value57|value21
awk
首先在split
上使用split
函数与|
输入字符串val
答案 1 :(得分:1)
这是一个bash
解决方案(if
语句是一个运行时优化,在没有匹配的情况下跳过重新配置,感谢@Inian):
for val in value1 value31; do
if [[ "$mystring" =~ \|$val|$val\| ]]; then
mystring=${mystring/$BASH_REMATCH/}
fi
done
这将在纯bash中查找与|value
或value|
匹配的第一个正则表达式并将其删除。请注意,您可以同时匹配两者,因为这样您将删除太多的分隔符。如果有可能没有分隔符,则需要在每个管道后使用?
(可能只是第二个就足够了)。
您还可以避免使用正则表达式,只是尝试删除前导管和后导管:
for val in value1 value31; do
mystring=${mystring/|$val/};
mystring=${mystring/$val|/};
done
如果你真的需要,所有这些都可以写在一行:
for val in value1 value31; do [[ "$mystring" =~ \|$val|$val\| ]]; mystring=${mystring/$BASH_REMATCH/}; done
答案 2 :(得分:0)
纯粹的bash解决方案:
#!/usr/bin/env bash
# Define the location of the values-to-be-removed file
: ${PATH_TO_FILE:=${1:-"./values_to_remove.txt"}}
# Define the string we will be working with
: ${MY_STRING:=${2:-"value1|value57|value31|value21"}}
# Process all entries in PATH_TO_FILE, one by one
while read -r substring || [[ -n "$line" ]]; do
# Remove "substring|" from the beginning of MY_STRING
MY_STRING=${MY_STRING#${substring}|}
# Remove "|substring" from the rest of MY_STRING
MY_STRING=${MY_STRING//|${substring}}
done < "${PATH_TO_FILE}"
# Return the results
echo ${MY_STRING}
为什么我们......
使用${VAR_NAME:=${1:-"DEFAULT_VALUE"}}
表示法 - 允许用户通过环境变量或脚本参数自定义脚本的输入。基本上,这种表示法说:
使用read -r substring || [[ -n "$line" ]]
读取文件? - read
允许我们逐行阅读./values_to_remove.txt
文件的内容。 [[ -n "$line" ]]
位用于捕获文件中的最后一行(如果它不以换行符结尾)。
<强>参考强>: