在 bash 中调用以 base64 解码的函数
Calling a function that decodes in base64 in bash
#!/bin/bash
#if there are no args supplied exit with 1
if [ "$#" -eq 0 ]; then
echo "Unfortunately you have not passed any parameter"
exit 1
fi
#loop over each argument
for arg in "$@"
do
if [ -f arg ]; then
echo "$arg is a file."
#iterates over the files stated in arguments and reads them $
cat $arg | while read line;
do
#should access only first line of the file
if [ head -n 1 "$arg" ]; then
process line
echo "Script has ran successfully!"
exit 0
#should access only last line of the file
elif [ tail -n 1 "$arg" ]; then
process line
echo "Script has ran successfully!"
exit 0
#if it accesses any other line of the file
else
echo "We only process the first and the last line of the file."
fi
done
else
exit 2
fi
done
#function to process the passed string and decode it in base64
process() {
string_to_decode = ""
echo "$string_to_decode = " | base64 --decode
}
基本上我想要这个脚本做的是遍历传递给脚本的参数,然后如果它是一个文件然后调用在 base64 中解码的函数,但只是在所选文件的第一行和最后一行.不幸的是,当我 运行 它即使调用了正确的文件也什么都不做。我认为代码的 if [ head -n 1 "$arg" ]; then
部分可能会遇到问题。有什么想法吗?
编辑:所以我明白我实际上只是一遍又一遍地提取第一行,而没有真正将它与任何东西进行比较。所以我尝试将代码的 if 条件更改为:
first_line = $(head -n 1 "$arg")
last_line = $(tail -n 1 "$arg")
if [ first_line == line ]; then
process line
echo "Script has ran successfully!"
exit 0
#should access only last line of the file
elif [ last_line == line ]; then
process line
echo "Script has ran successfully!"
exit 0
我的目标是遍历文件,例如一个看起来像这样的文件:
MTAxLmdvdi51awo=
MTBkb3duaW5nc3RyZWV0Lmdvdi51awo=
MXZhbGUuZ292LnVrCg==
并解码每个文件的第一行和最后一行。
是的,正如其他人所说,脚本的真正目标并不十分明确。也就是说,我想你可能想做的每一个变化都会被这样的东西所涵盖:
#!/bin/bash
process() {
encoded="";
decoded="$( echo "${encoded}" | base64 --decode )";
echo " Value ${encoded} was decoded into ${decoded}";
}
(( $# )) || {
echo "Unfortunately you have not passed any parameter";
exit 1;
};
while (( $# )) ; do
arg=""; shift;
if [[ -f "${arg}" ]] ; then
echo "${arg} is a file.";
else
exit 2;
fi;
content_of_first_line="$( head -n 1 "${arg}" )";
echo "Content of first line: ${content_of_first_line}";
process "${content_of_first_line}";
content_of_last_line="$( tail -n 1 "${arg}" )";
echo "Content of last line: ${content_of_last_line}";
process "${content_of_last_line}";
line=""; linenumber=0;
while IFS="" read -r line; do
(( linenumber++ ));
echo "Iterating over all lines. Line ${linenumber}: ${line}";
process "${line}";
done < "${arg}";
done;
一些您可能会觉得有用的补充:
如果使用多个文件名调用脚本,假设有 4 个不同的文件名,并且第二个文件不存在(但其他文件存在),
您真的希望脚本:处理第一个文件,然后注意到第二个文件不存在,然后退出吗?不处理(可能有效的)第三和第四个文件?
替换行:
exit 2;
和
continue;
会让它跳过任何无效的文件名,并且仍然处理后面的有效文件名。
此外,在您的 process 函数中,直接在行之后:
decoded="$( echo "${encoded}" | base64 --decode )";
如果该行不是有效的 base64,您可以在回显任何结果垃圾之前检查解码是否成功。
if [[ "$?" -eq 0 ]] ; then
echo " Value ${encoded} was decoded into ${decoded}";
else
echo " Garbage.";
fi;
--
为了回答您关于 IFS/read-construct 的后续问题,它是几个组件的混合体:
read -r line
从输入中读取一行(-r 告诉它不要做任何时髦的反斜杠转义魔术)。
while ... ; do ... done ;
这个while循环围绕着read语句,让我们不断重复读取一行的过程,直到我们运行出来。
< "${arg}";
这将文件名 $arg 的内容作为输入馈入整个代码块(因此这成为 read 语句从中读取的源)
IFS=""
这告诉读取语句使用空值而不是真正的内置 IFS 值(内部字段分隔符)。对每个读取语句执行此操作通常是个好主意,除非您有需要将行拆分为多个字段的用例。
如果不是
IFS="" read -r line
你要使用
IFS=":" read -r username _ uid gid _ homedir shell
并从 /etc/passwd 中读取,其中包含以下行:
root:x:0:0:root:/root:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
那么 IFS 值将允许它将这些值加载到正确的变量中(换句话说,它将拆分为“:”)
IFS 的默认值是从您的 shell 继承的,它通常包含 space 和制表符,可能还有一些其他内容。当您只读入一个变量时(在您的情况下为 $line)。 IFS 未应用,但当您更改读取语句并添加另一个变量时,分词开始生效并且缺少本地 IFS= 值将使完全相同的脚本在不同情况下表现非常不同。因此,始终控制它往往是一个好习惯。
引用变量也是如此,例如 "$arg" 或 "${arg}" ,而不是 $arg 。 ARG="hello" 什么时候没关系;但是一旦值开始包含 spaces 突然各种事情都会发生变化;惊喜从来都不是好事。
要解码提供给脚本的每个文件的第一行和最后一行,请使用:
#! /bin/bash
for file in "$@"; do
[ -f "$file" ] || exit 2
head -n1 "$file" | base64 --decode
tail -n2 "$file" | base64 --decode
done
#!/bin/bash
#if there are no args supplied exit with 1
if [ "$#" -eq 0 ]; then
echo "Unfortunately you have not passed any parameter"
exit 1
fi
#loop over each argument
for arg in "$@"
do
if [ -f arg ]; then
echo "$arg is a file."
#iterates over the files stated in arguments and reads them $
cat $arg | while read line;
do
#should access only first line of the file
if [ head -n 1 "$arg" ]; then
process line
echo "Script has ran successfully!"
exit 0
#should access only last line of the file
elif [ tail -n 1 "$arg" ]; then
process line
echo "Script has ran successfully!"
exit 0
#if it accesses any other line of the file
else
echo "We only process the first and the last line of the file."
fi
done
else
exit 2
fi
done
#function to process the passed string and decode it in base64
process() {
string_to_decode = ""
echo "$string_to_decode = " | base64 --decode
}
基本上我想要这个脚本做的是遍历传递给脚本的参数,然后如果它是一个文件然后调用在 base64 中解码的函数,但只是在所选文件的第一行和最后一行.不幸的是,当我 运行 它即使调用了正确的文件也什么都不做。我认为代码的 if [ head -n 1 "$arg" ]; then
部分可能会遇到问题。有什么想法吗?
编辑:所以我明白我实际上只是一遍又一遍地提取第一行,而没有真正将它与任何东西进行比较。所以我尝试将代码的 if 条件更改为:
first_line = $(head -n 1 "$arg")
last_line = $(tail -n 1 "$arg")
if [ first_line == line ]; then
process line
echo "Script has ran successfully!"
exit 0
#should access only last line of the file
elif [ last_line == line ]; then
process line
echo "Script has ran successfully!"
exit 0
我的目标是遍历文件,例如一个看起来像这样的文件:
MTAxLmdvdi51awo=
MTBkb3duaW5nc3RyZWV0Lmdvdi51awo=
MXZhbGUuZ292LnVrCg==
并解码每个文件的第一行和最后一行。
是的,正如其他人所说,脚本的真正目标并不十分明确。也就是说,我想你可能想做的每一个变化都会被这样的东西所涵盖:
#!/bin/bash
process() {
encoded="";
decoded="$( echo "${encoded}" | base64 --decode )";
echo " Value ${encoded} was decoded into ${decoded}";
}
(( $# )) || {
echo "Unfortunately you have not passed any parameter";
exit 1;
};
while (( $# )) ; do
arg=""; shift;
if [[ -f "${arg}" ]] ; then
echo "${arg} is a file.";
else
exit 2;
fi;
content_of_first_line="$( head -n 1 "${arg}" )";
echo "Content of first line: ${content_of_first_line}";
process "${content_of_first_line}";
content_of_last_line="$( tail -n 1 "${arg}" )";
echo "Content of last line: ${content_of_last_line}";
process "${content_of_last_line}";
line=""; linenumber=0;
while IFS="" read -r line; do
(( linenumber++ ));
echo "Iterating over all lines. Line ${linenumber}: ${line}";
process "${line}";
done < "${arg}";
done;
一些您可能会觉得有用的补充:
如果使用多个文件名调用脚本,假设有 4 个不同的文件名,并且第二个文件不存在(但其他文件存在), 您真的希望脚本:处理第一个文件,然后注意到第二个文件不存在,然后退出吗?不处理(可能有效的)第三和第四个文件? 替换行:
exit 2;
和
continue;
会让它跳过任何无效的文件名,并且仍然处理后面的有效文件名。
此外,在您的 process 函数中,直接在行之后:
decoded="$( echo "${encoded}" | base64 --decode )";
如果该行不是有效的 base64,您可以在回显任何结果垃圾之前检查解码是否成功。
if [[ "$?" -eq 0 ]] ; then
echo " Value ${encoded} was decoded into ${decoded}";
else
echo " Garbage.";
fi;
--
为了回答您关于 IFS/read-construct 的后续问题,它是几个组件的混合体:
read -r line
从输入中读取一行(-r 告诉它不要做任何时髦的反斜杠转义魔术)。
while ... ; do ... done ;
这个while循环围绕着read语句,让我们不断重复读取一行的过程,直到我们运行出来。
< "${arg}";
这将文件名 $arg 的内容作为输入馈入整个代码块(因此这成为 read 语句从中读取的源)
IFS=""
这告诉读取语句使用空值而不是真正的内置 IFS 值(内部字段分隔符)。对每个读取语句执行此操作通常是个好主意,除非您有需要将行拆分为多个字段的用例。
如果不是
IFS="" read -r line
你要使用
IFS=":" read -r username _ uid gid _ homedir shell
并从 /etc/passwd 中读取,其中包含以下行:
root:x:0:0:root:/root:/bin/bash
apache:x:48:48:Apache:/usr/share/httpd:/sbin/nologin
那么 IFS 值将允许它将这些值加载到正确的变量中(换句话说,它将拆分为“:”)
IFS 的默认值是从您的 shell 继承的,它通常包含 space 和制表符,可能还有一些其他内容。当您只读入一个变量时(在您的情况下为 $line)。 IFS 未应用,但当您更改读取语句并添加另一个变量时,分词开始生效并且缺少本地 IFS= 值将使完全相同的脚本在不同情况下表现非常不同。因此,始终控制它往往是一个好习惯。
引用变量也是如此,例如 "$arg" 或 "${arg}" ,而不是 $arg 。 ARG="hello" 什么时候没关系;但是一旦值开始包含 spaces 突然各种事情都会发生变化;惊喜从来都不是好事。
要解码提供给脚本的每个文件的第一行和最后一行,请使用:
#! /bin/bash
for file in "$@"; do
[ -f "$file" ] || exit 2
head -n1 "$file" | base64 --decode
tail -n2 "$file" | base64 --decode
done