为什么在这个使用for循环的pythonner中语法无效?
我正在编写Bash脚本。在其中,有几次我需要解析一些JSON。我通常的做法如下:为什么在这个使用for循环的pythonner中语法无效?,python,bash,Python,Bash,我正在编写Bash脚本。在其中,有几次我需要解析一些JSON。我通常的做法如下: MY_JSON=$(some command that prints JSON to stdout) RESULT=$(python -c "import json,sys;data=json.load(sys.stdin); python code here that prints out the value(s) I need") 这往往很有效。然而,昨天我遇到了一个问题。我有以下代码: MY_JSON=$(
MY_JSON=$(some command that prints JSON to stdout)
RESULT=$(python -c "import json,sys;data=json.load(sys.stdin); python code here that prints out the value(s) I need")
这往往很有效。然而,昨天我遇到了一个问题。我有以下代码:
MY_JSON=$(command that returns JSON containing an array of IDs)
IDS=$(echo "${MY_JSON}" | python -c "import json,sys;data=json.load(sys.stdin); for a in data['array']: print(a['id'])")
当我运行该代码时,我得到了“语法错误”,插入符号指向for
中的f
在我的谷歌搜索中,我发现的一切都表明,当你在语句的第一个字符上出现语法错误时,通常意味着你在上一个语句中搞错了什么。但是,如果完全删除for循环,则不会出现语法错误。显然,问题在于循环
我做错了什么?语法错误怎么可能是有效关键字的第一个字符
我最终找到了答案,我将在下面发布这篇文章,以帮助其他试图构建包含for
循环的Python一行程序的人——但我希望有人能提供更好的答案,也许可以使用理解(我不完全理解)或者其他一些东西,而不是for循环,这样我就可以在一行中完成这项工作。使用Python以外的语言也是可以接受的,只要它是Linux主机上典型的可用语言
明确地说,我将寻找使用真正的JSON解析的解决方案,而不是使用您最喜欢的字符串操作工具(
sed
,awk
,等等)的近似方法,这些方法在JSON打印是否美观等方面都很脆弱。这原来是由Python使用语义空白造成的。Python老手可能马上就知道了,但我只是涉猎了一下,所以这让人困惑。我会解释的
经过广泛的搜索,我得出了一个想法,也许压痕就是问题所在。其他人则收到缩进问题导致的语法错误
Python使用缩进而不是可见字符来确定语义代码块(如循环体)的边界。在类似C的语言中(这是我最熟悉的地方——Java、C#等),我们使用大括号来表示:
for (var i in myArray) {
i.doSomething();
printSomething(i);
}
所有空格都不重要,因此很容易将其转换为一行(尽管这在C风格语言中并不常见:
for (var i in myArray) { i.doSomething(); printSomething(i); }
因此,我尝试的下一件事是更加注意分号后面的空格。我的for循环是“缩进”一个空格,而import
和json.load
行没有前导空格。因此我去掉了那个空格(为了简洁起见,我省略了一些周围的代码):
这没有帮助。我的下一个想法是,分号可能不够,我需要实际的换行符。我迭代了一点,得出了以下结论:
MY_JSON=$(command that returns JSON containing an array of IDs)
IDS=$(echo "${MY_JSON}" | python -c "import json,sys;data=json.load(sys.stdin);
for a in data['array']:
print(a['server_id'])")
for
语句和循环体都需要在实际的单独行上,体缩进比for
更深。请注意,这段bash脚本位于if
的体中,因此都是缩进的。在我的实验中,我找不到一个在for的体中起作用的安排de>循环本身从任何地方开始,但不是从行的最开始
最终的结果不是很好,但很有效。这被证明是由Python使用语义空白造成的。Python老手可能马上就知道了这一点,但我只是浅尝辄止,所以这让人困惑。我会解释的
经过广泛的搜索,我发现可能是缩进造成了问题。其他人也发现了由缩进问题引起的语法错误
Python使用缩进而不是可见字符来确定语义代码块(如循环体)的边界。在类似C的语言中(这是我最熟悉的——Java、C#等),我们使用大括号来表示:
for (var i in myArray) {
i.doSomething();
printSomething(i);
}
所有空格都不重要,因此很容易将其转换为一行(尽管这在C风格语言中并不常见:
for (var i in myArray) { i.doSomething(); printSomething(i); }
因此,我尝试的下一件事是更加注意分号后面的空格。我的for循环是“缩进”一个空格,而import
和json.load
行没有前导空格。因此我去掉了那个空格(为了简洁起见,我省略了一些周围的代码):
这没有帮助。我的下一个想法是,分号可能不够,我需要实际的换行符。我迭代了一点,得出了以下结论:
MY_JSON=$(command that returns JSON containing an array of IDs)
IDS=$(echo "${MY_JSON}" | python -c "import json,sys;data=json.load(sys.stdin);
for a in data['array']:
print(a['server_id'])")
for
语句和循环体都需要在实际的单独行上,体缩进比for
更深。请注意,这段bash脚本位于if
的体中,因此都是缩进的。在我的实验中,我找不到一个在for的体中起作用的安排de>循环本身从任何地方开始,但不是从行的最开始
最终的结果不是很好,但很有效。中的语句分为两组,简单语句和复合语句:
stmt: simple_stmt | compound_stmt
只有简单语句才能包含;
,并且简单语句仅限于所谓的小语句:
stmt: simple_stmt | compound_stmt
小型语句不包括for
循环
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
相反,for
循环的是一个复合语句:
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
composite|stmt:if|stmt | while|stmt | for|stmt | try|stmt | with|stmt | funcdef | classdef | def | def | def | def |修饰| async| stmt
stmt: simple_stmt | compound_stmt
只有简单语句才能包含;
,并且简单语句仅限于所谓的小语句:
stmt: simple_stmt | compound_stmt
小型语句不包括for
循环
small_stmt: (expr_stmt | del_stmt | pass_stmt | flow_stmt |
import_stmt | global_stmt | nonlocal_stmt | assert_stmt)
相反,for
循环的是一个复合语句:
compound_stmt: if_stmt | while_stmt | for_stmt | try_stmt | with_stmt | funcdef | classdef | decorated | async_stmt
composite|stmt:if|stmt | while|stmt | for|stmt | try|stmt | with|stmt | functdef | classdef | def | def | defined | async| stmt
使用语言