将“-I”标志添加到 bash 中的路径字符串
Add "-I" flag to string of paths in bash
有一串 space 分隔路径,相对或绝对,示例:
/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd
我如何在 bash 中处理这个以便在这些路径中的每一个前面加上 -I?示例输出应为:
-I/aaaa/bbbb/ccc -I/ddas/sdsa/dasd -I./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer -I../dasd/dsad -I../../sdasd/sdsd
谢谢
编辑上下文:
正如你们中的一些人可能已经猜到的那样,这样做的目的是为 gcc 命令在文件夹路径前加上 -I 标志。
我在 makefile 中使用它。以下(根据 anubhava 的建议略作修改)完美运行:
#to include subdirectories in source
TEMP := $(shell find $(SOURCE_PATH)* -type d)
TEMP := $(shell echo $(TEMP) | awk 1 ORS=' ')
TEMP := $(shell printf -- "-I%s " ${TEMP} )
ifdef TEMP
INC_PATHS += $(TEMP)
endif
如果路径在数组中:
paths=(/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd)
那么您可以使用 bash 的查找和替换语法:
includes=("${paths[@]/#/-I}")
您可以提供数组作为命令(或函数)的一系列参数:
compile $the_file "${includes[@]}"
您可以在 bash 函数
中对 $@
(在引号中)进行类似的转换
with_includes() {
# If you need to do something with the first few arguments,
# collect them here and then call shift:
# the_file=; shift
# But you need to check $# to make sure the arguments exist :)
local includes=("{@/#/-I}")
compile $the_file "${includes[@]}"
}
您可以使用 printf
:
s='/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd'
printf -v output -- "-I%s " $s
echo "$output"
-I/aaaa/bbbb/ccc -I/ddas/sdsa/dasd -I./dasd/dsd -Idasd/dsda/dsd -Idsd/dsad/erer/rerer -I../dasd/dsad -I../../sdasd/sdsd
或者如果使用数组:
arr=(/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd)
printf -v output -- "-I%s " "${arr[@]}"
#!/usr/local/bin/bash
echo "/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd" | \
sed s'/ / -I/'g
不过,我同意其他人的看法,这是一种糟糕的形式。理想情况下,您的路径应该在单独的一行上。
#!/usr/local/bin/bash
echo "/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd \
dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd" | \
tr ' ' '\n' > tempfile
let "lines=$(wc -l tempfile | cut -d' ' -f1)"
let "lines=lines+1"
let "counter=1"
function loop() {
[ "${counter}" -lt "${lines}" ] && \
echo "Current loop iteration: ${counter}." && \
sed -n "${counter}p" tempfile | sed s'@^@ -I@'g >> tempfile2 && \
let "counter=counter+1" && \
loop
}
loop
[ -f ./tempfile ] && \
echo "File exists: ./tempfile." && \
rm ./tempfile
[ ! -f ./tempfile ] && \
echo "File deleted: ./tempfile."
然后您可以编辑 tempfile2 中每一行的开头以执行任何操作,并且 运行 将其作为 shell 脚本。
Inb4"Oh God no, he's using test! That could accidentally create an infinite loop! WE'RE ALL GOING TO DIE!"
无限循环并不是世界末日。它会导致的最坏情况是段错误。有时它们甚至很有用。 OP,您需要确保在测试块中的每个命令末尾都包含“&& \”(不带引号);当然最后一个除外
我学会了这样做是因为我在 Sparta OpenBSD 上花了很多时间,其中 rm 和大多数其他实用程序没有 -v 标志,我们也没有不怕无限循环。 ;)
有一串 space 分隔路径,相对或绝对,示例:
/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd
我如何在 bash 中处理这个以便在这些路径中的每一个前面加上 -I?示例输出应为:
-I/aaaa/bbbb/ccc -I/ddas/sdsa/dasd -I./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer -I../dasd/dsad -I../../sdasd/sdsd
谢谢
编辑上下文: 正如你们中的一些人可能已经猜到的那样,这样做的目的是为 gcc 命令在文件夹路径前加上 -I 标志。 我在 makefile 中使用它。以下(根据 anubhava 的建议略作修改)完美运行:
#to include subdirectories in source
TEMP := $(shell find $(SOURCE_PATH)* -type d)
TEMP := $(shell echo $(TEMP) | awk 1 ORS=' ')
TEMP := $(shell printf -- "-I%s " ${TEMP} )
ifdef TEMP
INC_PATHS += $(TEMP)
endif
如果路径在数组中:
paths=(/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd)
那么您可以使用 bash 的查找和替换语法:
includes=("${paths[@]/#/-I}")
您可以提供数组作为命令(或函数)的一系列参数:
compile $the_file "${includes[@]}"
您可以在 bash 函数
中对$@
(在引号中)进行类似的转换
with_includes() {
# If you need to do something with the first few arguments,
# collect them here and then call shift:
# the_file=; shift
# But you need to check $# to make sure the arguments exist :)
local includes=("{@/#/-I}")
compile $the_file "${includes[@]}"
}
您可以使用 printf
:
s='/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd'
printf -v output -- "-I%s " $s
echo "$output"
-I/aaaa/bbbb/ccc -I/ddas/sdsa/dasd -I./dasd/dsd -Idasd/dsda/dsd -Idsd/dsad/erer/rerer -I../dasd/dsad -I../../sdasd/sdsd
或者如果使用数组:
arr=(/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd)
printf -v output -- "-I%s " "${arr[@]}"
#!/usr/local/bin/bash
echo "/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd" | \
sed s'/ / -I/'g
不过,我同意其他人的看法,这是一种糟糕的形式。理想情况下,您的路径应该在单独的一行上。
#!/usr/local/bin/bash
echo "/aaaa/bbbb/ccc /ddas/sdsa/dasd ./dasd/dsd dasd/dsda/dsd \
dsd/dsad/erer/rerer ../dasd/dsad ../../sdasd/sdsd" | \
tr ' ' '\n' > tempfile
let "lines=$(wc -l tempfile | cut -d' ' -f1)"
let "lines=lines+1"
let "counter=1"
function loop() {
[ "${counter}" -lt "${lines}" ] && \
echo "Current loop iteration: ${counter}." && \
sed -n "${counter}p" tempfile | sed s'@^@ -I@'g >> tempfile2 && \
let "counter=counter+1" && \
loop
}
loop
[ -f ./tempfile ] && \
echo "File exists: ./tempfile." && \
rm ./tempfile
[ ! -f ./tempfile ] && \
echo "File deleted: ./tempfile."
然后您可以编辑 tempfile2 中每一行的开头以执行任何操作,并且 运行 将其作为 shell 脚本。
Inb4"Oh God no, he's using test! That could accidentally create an infinite loop! WE'RE ALL GOING TO DIE!"
无限循环并不是世界末日。它会导致的最坏情况是段错误。有时它们甚至很有用。 OP,您需要确保在测试块中的每个命令末尾都包含“&& \”(不带引号);当然最后一个除外
我学会了这样做是因为我在 Sparta OpenBSD 上花了很多时间,其中 rm 和大多数其他实用程序没有 -v 标志,我们也没有不怕无限循环。 ;)