Sunday, January 29, 2023

通过引用机制绕过 shell

使用 echo 命令

shell 都内置 echo 命令。如果你想看看 shell 如何解释元字符(meta-characters),在命令的前面加上“echo”。

例如,你想知道键入下面这一行命令会发生什么

% ls *

我建议你先键入

% echo ls *

看看结果如何。

shell 认为“*”是一个特殊字符,shell 看到“*”的时候,会更改“*”来匹配当前目录中的文件,然后调用“ls”命令,并传输这些参数给“ls”。“ls”命令永远看不到“*”字符。

假设你的目录中有一个文件名中带有“*”,你如何列出或删除该文件?你必须引用 “*”才能将它传送给 shell。

你可以使用三种引用机制(quoting mechanisms),它们分别是单引号(single quote)、双引号(double quote)和反斜杠(backslash)。

用反斜杠引用单个字符

你可以在字符前面放置一个反斜杠(“\”)来防止 shell 解释该字符。

你可以使用下面这条命令列出带有“*”的文件:

% ls *\**

下面是一个 shell 脚本,它可以删除任何包含星号的文件:

echo contain an asterisk in the name
echo This script removes all files that

echo
echo Are you sure you want to remove these files\?
rm -i *\**

在问号的前面也需要反斜杠,因为它也是一个 shell 元字符。没有反斜杠,shell 将查找与模式“files?”匹配的所有文件。如果有文件“files1”和“files2”,脚本将打印出来

Are you sure you want to remove these files1 files2

这不是你想要的结果。这又是一个很好例子——在有疑问时最好使用引号。在这个教程的示例中我并没有总是这么做,因为了解内部工作原理很重要。有时我会在本教程中使用不好的例子来强调细节。
 
反斜杠是 “最强” 的引用方式。当所有其他方法都失败时,它会起作用。如果你想将文本放在两行或多行以提高可读性,但程序其实只有一行,那么你需要一个行继续符。只需使用反斜杠作为该行的最后一个字符即可:

% echo This could be \
a very \

long line\!

This could be a very long line!

%

反斜杠会转义(escape)或引用行尾字符(end of line character),迫使它不再具有特殊含义。在上面的例子中,我还在感叹号前加了一个反斜杠。如果你使用的是将 “!” 当作一个特殊符号的 C shell,那么这么做是必需的。如果你使用的是其他 shell,则可能没有必要这么做。

单引号格式的强引用

当你需要一次引用多个字符时,你可以使用多个反斜杠:

% echo a\ \ \ \ \ \ \ b

('a' 和 'b' 之间有 7 个空格。)这个命令很丑陋但有效。使用成对的引号来指示要引用的字符的开始和结束会更容易:

% echo 'a       b'

在单引号内,你可以包含几乎所有元字符:

% echo 'What the *heck* is a $ doing here???'
What the *heck* is a $ doing here???

上面的示例使用了星号、美元符号和问号元字符。当您希望文本保持原样时,应使用单引号。注意——如果你使用的是 C shell,则“!”字符之前可能需要一个反斜杠。这取决于它旁边的字符。如果它被空格包围,则不需要使用反斜杠。

双引号格式的弱引用

有时你需要一种较弱的引用类型:一种不扩展元字符(如“*”或“?”)但扩展变量并进行命令替换的引用。这可以用双引号来完成:

% echo "Is your home directory $HOME?"
Is your home directory /home/barnett?
% echo "Your current directory is `pwd`"
Your current directory is /home/barnett
# This next example won't work in the C shell and Bourne shell
% echo "Your current directory is $(pwd)"
Your current directory is /home/barnett

一旦了解了单引号和双引号之间的区别,你将掌握一项非常有用的技能。这并不难。单引号比双引号强。知道了吗?好的。反斜杠是最强的。

在文件名中包含空格和字符时使用引号

如果要处理文件名中包含空格或特殊字符的文件,则可能必须使用引号。例如,如果你想创建一个名称中有空格的文件,你可以使用以下方法:

% cp /dev/null 'a file with spaces in the name'

通常,shell 使用空格来确定每个参数的结尾。引用改变了这一点,上面的例子只有两个参数。你还可以在字符前使用反斜杠。下面的例子重命名文件名带有空格的文件,将空格替换为下划线:

% mv a\ file a_file

使用相同的技巧,你可以处理文件名中的任何字符:

% mv a 'a?'

在最坏的情况下,有空格的文件名中会增加它用作参数的难度。但是,在文件名中使用其他字符则非常危险。

一个例子是文件名以连字符(hyphen)作为文件名的第一个字符。如果你有一个名为“-i”的文件并且你想删除它,下面的命令

% rm "-i"

将不起作用,因为“rm”命令将“-”解释为元字符——并假定参数是一个选项。解决方法是使用真实的 Unix 路径,以及“.”是当前目录的路径。因此,解决办法是键入:

% rm "./-i"

当在文件名中有“?”和“*”时会出现其他问题。如果要删除文件“a?”你最终可能会删除多个文件。我强烈建议你养成使用 “echo”检查有元字符时将要发生什么的习惯。

多重引用

虽然有两种类型的引用(如果算上反斜杠,则为三种)可能看起来令人困惑,实际上它提供了几种解决相同问题的方法。你可以将一种引用放在另一种引用内。如果要使用单引号,请在它的外面使用双引号。要使用双引号,请在它的外面使用单引号。使用例子更容易演示这一点:

$ echo Don't do that
> '
Dont do that
% echo "Don't do that"
Don't do that
% echo 'The quote of the day is: "TGIF"'
The quote of the day is: "TGIF"
%
 

找出引用是否错误

在某些情况下,在不确定时你可能需要使用反斜杠。在其他情况下,反斜杠也会出差错。 你怎么知道你引用的东西是否正确?答案:使用 shell。

检查引用的一种简单方法是在命令的前面添加一个“echo”,这样你就可以看到发生了什么,或者将一个“ls”命令更改为一个“echo”命令:

echo scp gateway:\*.tar.Z .
ssh user@cruncher echo ls \*
ssh user@cruncher echo 'ls *'

如果你想在远程机器上做文件重定向,echo 是不够的。当你希望命令回显到你的终端时,下面的命令

ssh user@cruncher echo 'ls * >/tmp/file'

将回显结果发送到文件。你需要嵌套引号:

ssh user@cruncher "echo 'ls * >/tmp/file'"
ssh user@cruncher 'echo "ls * >/tmp/file"'
ssh user@cruncher "echo 'cd newdir;ls * >>/tmp/file'"

如果你正在调试 shell 脚本,并且想查看你的脚本在做什么,你可以复制脚本中的重要行之一,并在其中一个重复项的前面插入一个“echo”。在脚本中执行此操作一两次并不是很困难,但有时你会想要查看脚本的每一行。在这种情况下,只需要求 shell 显示你想要的内容。

Posix/Bourne Shell 变量

POSIX 和 Bourne shell 有两个变量,设置后,将帮助你跟踪复杂的变量和元字符扩展。你可以在执行脚本时通过键入以下命令启用对 POSIX 和 Bourne shell 脚本的变量扩展:

% sh -v script
% sh -x script

你还可以在脚本中打开和关闭此功能。要打开 verbose 标志,请使用

set -v

要打开 echo 变量,请使用:

set -x

如果你想关闭这些变量,请使用加号而不是减号:

set +x
set +v

在引号内包含相同的引号

人们遇到的一个问题是在引号中包含相同的引号。许多人期望下面的方法起作用:

echo "The word for today is \"TGIF\""
echo 'Don\'t quote me'

第一个示例适用于 Bourne shell,但不适用于 C shell。第二个例子对它们都不起作用。我敢打赌你们中的许多程序员对此感到困惑。我曾是。通常,我们描述一个字符串,开头是“字符串的开头”,结尾是“字符串的结尾”。这两者之间是字符串。简单的。当你使用 shell 时,这有几分是正确的。与大多数编程语言不同,引号可以打开和关闭替换。它们不用于指示字符串的开始和结束。考虑下面这组引号:

echo 'a'b'c'

这被拆分为三个单元。第一个和最后一个被引用,中间没有。引用和替换发生后,三个单元被合并。中间部分不被引用(即允许被视为元字符),并且可以是一个变量,例如,我们可以将“b”更改为“$HOME”:

echo 'a'$HOME'b'

这种技术是将 shell 变量放入 awk 脚本的典型方法。下面是一个简单的 shell 脚本来演示这一点。请研究这个,因为它很重要:

#!/bin/sh
# this is a shell script that acts like a filter,
# but in only prints out one column.
# the value of the column is the argument
# to the script
#
# uncomment the next line to see how this works
#set -x
#
# example:
#       printcol 1
#       printcol 3
# the value of the argument is $1
# Here comes the tricky part -
awk '{print $'$1'}'
# I told you!

在此示例中,shell 将 awk 的参数分成三部分:

{print $ Quoted
$1 Evaluated
} Quoted

你可以取消注释命令“set -x”并使用下面的命令来尝试脚本

printcol 2 </etc/hosts

shell 脚本的参数是 2,因此计算“$1”并返回值“2”。这使得 awk 的参数成为字符串“print {$2}”并且第二列被打印出来。

请注意,此技术适用于使用任一种类型引号的任何 shell。

当你想在引号中引用引号时,你必须了解这一点。事实上,你不想将引号放在引号中,而是想将多个单元组合或连接成一个参数。

让我换个说法。如果要在以单引号开头的参数中包含单引号,则必须关闭以单引号开头的机制,并使用不同的引用方法。请记住,反斜杠是所有引用机制中最强大的。你可以用反斜杠引用任何内容。此示例引用所有三个引号字符:

% echo \'\"\\

结果是这样的

'"\

你始终可以使用反斜杠来引用字符。但是,在单引号机制中,“\'”并不“引用引号”。正确的方法如下:

% echo 'Don'   \'   't do that'
Don ' t do that

我放了一些额外的空格,这样你就可以了解发生了什么。这里没有多余的空格:

% echo 'Don'\''t do that'
Don't do that

当你在脑海中解析 shell 脚本时,请记住将引号匹配在一起。这也适用于双引号:

% echo "The quote for today is "\"TGIF\"
The quote for today is "TGIF"

或者,如果你想在“TGIF”周围加上引号

% echo "The quote for today is "\""TGIF"\"
The quote for today is "TGIF"

引用长行

大多数 Unix 程序也使用反斜杠来转义特殊字符。Unix 实用程序通常将行尾的反斜杠解释为续行符——也就是说,行尾字符被引号或转义,因此无法使用其标准含义。

当你引用超出行尾标记的行时,Bourne shell 和 C shell 的行为不同。C shell 不会将引号扩展到该行之外,除非最后一个字符是反斜杠:

% echo "A quote \
on two lines"
A quote
on two lines

Bourne shell 允许引号超出行:

$ echo "A quote
> on two lines"
A quote
on two lines

请注意 Bourne shell 如何在引用未结束时用“>”提示你。你们可以自己争论哪种行为是正确的。我可以理解 C shell 默认情况下不允许多行引用的原因。前面的例子:

echo 'Don\'t do that'

如果你使用 C shell,则会产生错误。但是,如果你使用 Bourne shell,你将得到一个“>”提示,并且该提示将一直持续到你键入单引号为止。这可能会让新的 Unix 用户感到困惑。

当我编写作为 awk 脚本的多行引号时,我发现 Bourne shell 更易于使用:

#!/bin/sh -x
#This script counts how many people
# are in the group specified as the first argument
grp=${1:?"Missing argument"}    # get group ID number
# If missing, report an error and exit.
awk -F: '
# Awk script starts here
BEGIN {
    # set total to zero
    #   before we start
    total=0;    
}
$3 ~ /^'$grp'$/ {total++;}
END {
    # end of file, print total
    printf("Total: %d\n", total);
}' </etc/passwd

此示例在 awk 脚本的中间使用了“$grp” shell 变量。这是将 shell 变量传递到 awk 脚本中间的常用方法。有些人更喜欢使用其他机制在字符串中使用动态变量。例如,awk 提供了另一种机制,但我鼓励你理解这种技术,因为它可以与其他实用程序一起使用。

 

Sunday, January 22, 2023

俗套吉利话的竞赛

春节祝福是俗套吉利话的竞赛。

我不想参与这种竞赛。

Saturday, January 21, 2023

Albert Camus 阿尔贝·加缪 - 如何发音?

Albert Camus 的维基词条点这里,是 1957 年诺贝尔文学奖得主。在这个词条里标注了 Albert Camus 的三个发音:

/kæˈmuː/ kam-OO, US also /kəˈmuː/ kə-MOO; French: [albɛʁ kamy]

分别列出了一般英语读法、美式英语读法、法语读法。

这个视频里剪辑了现实生活中各个场合下人们是怎么读的,几乎全部是美式英语。

+++++

阿尔贝·加缪

中文翻译几乎一律都是用“阿尔贝·加缪”,显然这个翻译来自法语的发音,因为 Albert 的英语翻译是“艾伯特”或“阿尔伯特”。但是“缪”是个多音字,可以 miù、mù、miào 三种最常见的发音,在百度上大家都说读 miù,在 YouTube 的中文视频也也都是如此,这个发音与法语的"my"都差别很大。

英式或者美式发音都是“木”,所以“miù”这个发音与英语的发音也差别很大。

Monday, January 16, 2023

Two Bone Roast Prime Rib 的做法探讨

一个 Two Bone Roast Prime Rib,一般一个家庭够吃一顿了。Sea Salt / Black Pepper / Garlic 均匀涂抹,温度达到了 450F 后再放入肉,30 分钟后烤箱关火,放 1 小时左右,再开火,200F 2 小时 30 分钟。

所有步聚,肉都是在烤箱内,不用拿出来。

Drogheria Garlic Mill Grinder 55g


The Ultimate Roasted Garlic & Sea Salt

烤肉可以提前一天 Seasoning,然后放冰箱,会更嫩。如果偷懒,稍微提前将肉拿出来,尽量放置 Room Temperature, 实在没时间,提前 1 小时拿出来。

看似很简单,450F 转 200F,无数次的试验,烤废掉的喂饱了多少后院动物。最近也是得到一位老 Butcher 的指导。

煎或明火烤,我是闭着眼睛都做得好。Slow Cook Roast Prime Rib 其实非常难,没人告诉你温度,你慢慢试试吧, 没有 5 位数的学费根本试不出来。

Roast Beef 讲究的是嫩,汁水保留,比如 3 磅的肉进去,出来应该也是 3 磅差不多重。柴了没法吃,配个土豆泥非常不错的。

我昨天说得烤肉温度肯定是对的,尤其是 450F 30 分钟,即便 3 bone 或者 4 bone 都是这样,但后面因为同样的 2 bone 重量是不同,油花的不同,加上每个家庭接受生熟程度不同,所以在450F 30 分钟之后关火放置 1 小时左右,再开火 200F,2 个半小时之后拿出来放置 10 分钟,从中间切开看看,如果觉得生,开火再放入200F,直到自己喜欢的程度, 肯定也要试验几次,可以找到您和家人最喜欢的烤肉。祝成功!

做事情要责任心,这样,你最多试验 3 次,一定可以找到自己最佳口味。200F 即便烤时间过长也不会柴。要点就是 low slow,所以 200F 在 2 个半小时之后,不满意,同样温度再烤,不用担心会烤坏,但建议每半小时切开看看。

YouTube 包括 Village Grocer 给出的配方,他们的 butcher 私下交流都说不是最好的方法。450F 和 200F 是最主要的,也有高手说 200F 以下效果更好,但时间太长,5 或 6 小时。

基本规律都是先高温快速 Seal 起来,然后慢慢搞熟。

对,低温慢火的效果,就是熟和嫩 Brisket 时间更长。我对门告诉我,他需要 20 小时。

我又在试验,人要有个爱好,学费就没法计较了,我还是在寻找 200F 之后最佳的出品。

我今天试下 200F 1.5 小时之后再低一点,3 小时左右。试试看。从现在开始,基本就是一天时间。

以今天这块大小为列,Two Bone 450F 半小时,关火,放置 1 小时,再 200F 2 小时 15 分钟到 30 分钟,应该可以让大部分人可以接受的熟度。 有些人一点点生都不行,那没法照顾了。真的要全熟, 应该再往后加 2 小时,因为 low- slow 也不会柴。

今天是小孩饿了急了,没拍照,我试验了到现在,应该这个温度配方,这个大小的肉,可以适合大部分人。


+++++

更新

还是烤肉啊,two bone 应该 450F,温度到达后,肉放入半小时,关火,放置一小时,再 200F 2小时,基本上年轻人可以接受。如果有老人,再多 30 分钟,应该可以接受的熟度。

下面这个是三根骨头的,我 200F 3 小时 30 分钟。所以我觉得年轻人 200F 2 小时应该可以了。老年人再加半小时。对了,肉拿出来一会,一定要静置 15 分钟左右再切。
 




 +++++

2 bone prime rib 实验结果

前面程序不变,后面 200F,具体多长时间,根据大小,根据自己经验,自己调整,肯定完美效果。其实最重要的是 200F,是经过无数试验出来的,时间长短是可以通过几次试验就掌握的。





+++++

更新:最新实验心得分享:450F 半小时,关火,放烤箱里2小时,再 200F 45 分钟到 60 分钟,放置 15 分钟,切。

Wednesday, January 11, 2023

标普 500 指数 2022 年熊市可能结束

标普 500 指数于 2022 年 1 月 3 日达到 4,796.56 点,是 2022 年熊市之前的最高点,然后开启了 2022 年的大熊市。2021 年 12 月 27 日到 2022 年 1 月 4 日都在 4,790 点上下,是牛市的顶峰。

2022 年 10 月 12 日标普 500 指数是 3,577.03,这可能是 2022 年熊市的结束点(最低点)。

股市下跌 1 - 3,577.03/4,796.56 = 25.43%,这在历史上都不算特别大的跌幅。标普 500 指数前几十年的熊市跌幅平均起来是 33.5%。

调整与熊市的常规定义:指数跌 10% 叫调整(market correction);指数跌 20% (至少两个月)叫熊市(bear market)。

+++++

道路是曲折的

2022 年 3 月 8 日指数是 4,170.70;2022 年 3 月 14 日指数是 4,173.11。这是第一个波谷。

2022 年 3 月 29 日指数是 4,631.60。这是第一个反弹。

2022 年 6 月 16 日指数是 3,666.77。这是第二个波谷,更低的波谷!

2022 年 8 月 16 日指数是 4,305.20。这是第二个反弹。

2022 年 10 月 12 日指数是 3,577.03。这是第三个波谷,更低的波谷。

2022 年 11 月 30 日指数是 4,080.11。这是第三个反弹。

2022 年 12 月 28 日指数是 3,783.22。这算是第四个波谷。这个波谷已经高于第三个和第二个波谷,开始了上升趋势。

如果第四个反弹超过第三个和第二个反弹,那么趋势就是明朗的。

当然道路可能比预计的要曲折一些。

+++++

今天收市情况

作为对比,今天 2022 年 1 月 11 日指数收市 3,969.61 点。相比之前牛市最高点,仍然下跌 17.24%,要涨 20.83% 才能达到之前的牛市最高点。

2022 年 12 月 30 日收盘指数是 3,839.50,要达到之前的牛市最高点,那么要涨 24.93%。我不认为 2023 年能涨那么多。

因此历时两年,指数还不能回到之前的最高点。大概率需要三年的时间。

2000 年泡沫花了七年时间恢复;2008 年危机花了五年时间恢复。

这是投资指数的一大弊端。不过可以用 DOLLAR COST AVERAGE - DCA 来克服这个弊端。前提是在低谷期间有 dollar 来投资,也就是需要持续的现金流,那么买指数是很稳定的。

当然你在大跌的波谷大批资金进入,那是肯定最理想的。所以,下跌超过 20% 我就推荐人买指数,下跌超过 30% 闭着眼睛买。

Wednesday, January 4, 2023

BMO InvestorLine 忘记要我填写 LIMITATION ON BENEFIT TREATY STATEMENT,多征收美股 Withholding tax

2022 年 1 月 4 日打开 BMO InvestorLine 账户,看到 MyLink 里有两条消息,点开一看,2022 年 12 月 15 日的那条消息十分重要,叫我在 2 月 15 日之前提交 LIMITATION ON BENEFIT TREATY STATEMENT。消息说我的账户从 2022 年 1 月起这个表格就没有更新了,全年美股的 dividend 都按照 30% 的比例收取 withholding tax。我赶快查了月结单,2021 年 12 月按照 15% 征收,2022 年按照 30% 征收。

BMO IL 竟然到 2022 年年底了才通知我更新这个表格。

BMO IL 竟然通过账户内消息的方式(MyLink)通知我。这么重要的文件,别的银行都会发正式邮件通知。

问题是 BMO IL 2.0 新版本没有任何地方显示 MyLink,所以没人会去看消息!

email 会通知有 MyLink 消息,但是在 email 里也不显示消息正文内容的。

MyLink 里的消息几乎都是垃圾消息。

还好我回到了旧版,还好我今天点了一下 MyLink。

BMO 的恶真是罄竹难书!