我强烈怀疑我的代码中grep
的最佳用法,并希望找到一种更好,更简洁的编码样式,以便从cookie文件中提取会话ID和安全级别:
cat mycookie
# Netscape HTTP Cookie File
# https://curl.haxx.se/docs/http-cookies.html
# This file was generated by libcurl! Edit at your own risk.
#HttpOnly_127.0.0.1 FALSE / FALSE 0 PHPSESSID 1hjs18icittvqvpa4tm2lv9b12
#HttpOnly_127.0.0.1 FALSE /mydir/ FALSE 0 security medium
预期的输出是SSID哈希值:
1hjs18icittvqvpa4tm2lv9b12
在命令行中用grep
管tr '\n' '\0'
就像一个超级按钮一样,但是在执行bash代码时会生成警告(warning: command substitution: ignored null byte in input
”)。以下是相关代码(带有警告):
ssid=$(grep -Po 'PHPSESSID.*' path/sessionFile | grep -Po '[a-z]|[0-9]' | tr '\n' '\0')
我正在使用bash 4.4.12 (x86_64-pc-linux-gnu)
,可以读到here这个清晰的解释:
Bash变量存储为C字符串。 C字符串以NUL终止。 因此,它们无法按照定义存储NUL。
在两种情况下,我都可以看到here和there是使用read
的编码解决方案:
# read content from stdin into array variable and a scalar variable "suffix"
array=( )
while IFS= read -r -d '' line; do
array+=( "$line" )
done < <(process that generates NUL stream here)
suffix=$line # content after last NUL, if any
# emit recorded content
printf '%s\0' "${array[@]}"; printf '%s' "$suffix"
在这种情况下,我不想使用数组或while
循环。我使用sed
找到了解决方法:
ssid=$(grep -Po 'PHPSESSID.*' path/sessionFile | grep -Po '[a-z]|[0-9]' | tr '\n' '_' | sed -e 's/_//g')
我的两个问题是:
1)是否可以在不使用tr '\n' '\0'
到read
循环中替代while
的更好方法?
2)正确提取SSID和安全级别是更好的方法吗?
Thx
答案 0 :(得分:2)
您似乎正在尝试摆脱grep
的输出中的换行符,但是将它们转换为null并不会这样做。空值在您的终端中不可见,但仍然存在,并且(像许多其他非打印字符一样)如果将其视为您的实际数据的一部分,将会造成严重破坏。如果您想摆脱换行符,只需告诉tr
用... | tr -d '\n'
为您删除它们。但是,如果您尝试从Netscape格式的cookie文件中获取PHPSESSID
值,则有更好的方法:
ssid=$(awk '($6 == "PHPSESSID") {print $7}' path/sessionFile)
这会在第六个字段中查找“ PHPSESSID”(仅 )(而不是在路径或cookie值中-都可以合法显示的两个位置),并专门打印匹配行的第七个字段(不仅是“ PHPSESSID”之后的任何数字或小写字母。
答案 1 :(得分:1)
如果您不想使用awk,也可以尝试以下方法:
ssid=$(grep -P '\bPHPSESSID\b' you_cookies_file)
echo $ssid # for debug only
输出类似
的内容#HttpOnly_127.0.0.1 FALSE / FALSE 0 PHPSESSID 1hjs18icittvqvpa4tm2lv9b12
然后使用cut(1)提取相关字段:
echo $ssid |cut -d" " -f7
输出
1hjs18icittvqvpa4tm2lv9b12
当然您应该捕获最后一个echo
。
更新
如果您不想使用cut,可以使用以下命令进行模拟:
echo $ssid | (read a1 b2 c3 d4 e5 f6 g7; echo $g7)
演示捕获变量:
$ field=$(echo $ssid | (read a1 b2 c3 d4 e5 f6 g7; echo $g7))
$ echo $field
1hjs18icittvqvpa4tm2lv9b12
$
另一种方法是使用位置参数,将字符串传递给一个函数,该函数随后引用$ 7。也许更干净。否则,您可以使用数组:
array=($(echo $ssid))
echo ${array[6]} # outputs the 7th field
也应该可以使用正则表达式和/或bash操作字符串,但对我来说似乎有点困难。