快速显示与正则表达式匹配的行子集的数据视图我正在寻找执行以下操作的 JSL 脚本:
-
获取活动数据表中当前选定的列。
-
选取第一个选定的列。
-
提示用户输入正则表达式。
-
仅选择表中该列中的值与正则表达式匹配的行。
-
打开“数据视图”窗口,仅显示匹配的行。
使用 JSL 可以实现这一点吗?
自动化和脚本数据访问回复:快速显示与正则表达式匹配的行子集的数据视图有可能。你尝试过什么方法吗?
这是一个非常基本的例子,缺少所有可以(并且很可能应该)实施的检查
Names Default To Here(1);
dt = Current Data Table();
col = (dt << Get Selected Columns("String"))[1]; // I suggest dropping non-character columns
run_expr = Expr(
rgx_pattern = teb << Get Text; // You could check if the pattern is valid regex
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
// add check if any rows have been selected
dt << Data View; // If linked subset is fine, that is most likely better as it can avoid using select where
dt << Clear Select;
wait(0);
);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("")
),
Lineup Box(N Col(1),
Button Box("OK",
run_expr
),
Button Box("Cancel")
)
)
);
Write();
回复:快速显示与正则表达式匹配的行子集的数据视图有用,谢谢。
说实话,我没有包含任何代码,因为我的尝试不是很接近,并且暴露了一些关于 JSL 的基本误解,这些误解可能来自于我从 AppleScript 和 Matlab 学习 GUI 脚本。
我本来想获取所选列名的列表,并选择第一个,但我期望某种返回字符串的“显示对话框”函数,但这显然不存在,并强制你使用这种“新窗口/列表框/按钮表达式”的语法,这对我来说相当不直观,但现在我明白了它的作用,就更容易理解了。我尝试了 ChatGPT,但它创建了很长的脚本,根本无法运行。
如果您有时间,请问关于您的解决方案的几个问题:
- 为什么“取消”按钮没有任何反应?我猜是因为你没有在 Button Box() 调用中传入第二个参数,但是哪个表达式可以关闭当前窗口呢?Close()?我试过“Button Box ( “取消” , 关闭 ())”,但它报了一个我无法理解的错误。我模仿你的方法,尝试了“关闭窗口”,似乎可以正常工作,但我希望有更简洁的方法。
- 您的“Get Selected Columns()”调用以“String”作为参数,但文档显示该函数不接受任何参数。“String”在这里是什么意思?您如何知道它会被接受,或者它的作用是什么?
- 我想在运行脚本后立即开始输入,但焦点不在正确的位置。我尝试在“nw=...”表达式后运行“teb << SetFocus;”,但 JMP 显示文本编辑框无法识别该消息。
- 是否可以让 Regex 不区分大小写,如果可以,怎么做?(我尝试添加“ “根据文档将其添加到 Regex 参数中,但会出现错误。)
- 是否可以让 return/enter 在 teb 框聚焦的情况下触发“Ok”脚本?
- 如果用户没有选择列,我想使用第一个字符列,但经过大约 20 次不同的尝试后,我放弃了尝试找出那是哪一列。
- 我希望数据视图子集能够链接起来,这会改变方法吗?
以下是我目前所掌握的信息:
Names Default To Here(1);
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns("String");
if(N Items(selCols)==0, selCols = dt << get column names("String") );
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt << Data View; // I prefer a linked subset, what changes here?
dt << Clear Select;
wait(0);
nw << Close Window;
);
close_expr = Expr(nw << Close Window);
nw = New Window("",
H List Box(
Lineup Box(N Col(2),
Text Box("Enter regex pattern"),
teb = Text Edit Box("", <
<SET width=""></SET>
<P>我喜欢打开 Big Class,运行脚本,然后输入“ob.+t<ENTER> “并让它显示仅包含两个罗伯特的数据视图。现在它已经关闭了——运行脚本后,我必须按下 Tab 键,然后按 OB.+T,然后输入两次。</ENTER></P>
回复:快速显示与正则表达式匹配的行子集的数据视图- 我创建了尽可能小的示例,因此“取消”不包含关闭窗口的表达式
- 我刚刚试了一下“String”值是否能像<< get column names()那样工作,结果确实如此。测试一下不使用“String”值,看看会得到什么(引用而不是字符串)。在我看来,使用列引用简直是一场噩梦,所以我总是使用列名的字符串,并根据需要进行转换。但是否使用引用(或任何冒号语法)完全取决于你。
- 我认为除非您希望使用复杂的解决方法,否则您将被困在标签中,允许 SetFocus 与交互式显示元素(TextEditBox、Button......)一起使用
- 您可以将用户输入转换为 Lowercase(),并用 Lowercase() 包装列引用。或者,我认为您可以在使用 INGORECASE 时将默认捕获组添加到 Regex(): 正则表达式(“ABCD”, “d”, “\0”, 忽略大小写)
- 您可以尝试<<设置函数,它能满足您的需求。它会在提交时执行脚本,按下回车键应该会触发该操作(就像在文本编辑框外部单击一样)。
-
<< Get Column Names(Character, String)[1]
-
r = dt << Get Rows Where(!Is Missing(Regex(Column(dt, col)[Row()], rgx_pattern)));
dt_subset = dt << Subset(Rows(dt), Selected Columns(0), Link to original data table(1));
有很多可以改进的地方,但具体改进什么则取决于实际用例。
编辑:将原始数据表(1)的链接添加到子集
回复:快速显示与正则表达式匹配的行子集的数据视图非常好,谢谢!
还有一个问题:如果选择了多列,我想对连接在一起作为字符串的列值执行正则表达式;如果没有选择任何列,我想对*所有*列执行同样的操作。这实际上模拟了 egrep 在表上的行为。这合理可行吗?请参阅下面的注释行,这是我的初步尝试,但它不会只从选定的列中提取值,所以它还没有达到这个目的(并且无法正常工作)。
Names Default To Here( 1 );
run_expr = Expr(
dt = Current Data Table();
selCols = dt << Get Selected Columns( "String" );
If( N Items( selCols ) == 0,
selCols = dt << Get Column Names( "String" )
);
col = selCols[1];
rgx_pattern = teb << Get Text;
dt << Select Where( !Is Missing( Regex( Column( dt, col )[Row()], rgx_pattern, "1", IGNORECASE ) ) );
// dt << Select Where( !Is Missing( Regex( Concat Items( dt << get Rows(Row())," "), rgx_pattern, "1", IGNORECASE ) ) );
dt << Data View;
Wait( 0 );
);
close_expr = Expr( nw << Close Window; Wait( 0 ); );
nw = New Window( "Table Egrep",
H List Box(
lb1 = Lineup Box( N Col( 2 ),
Text Box( "Select column to Enter regex pattern" ),
teb = Text Edit Box( "", Set Script( run_expr ), <
<SET width=""></SET>
<P>仅供参考,上面的“设置脚本”处理了“输入”后立即执行的操作,效果很好。唯一缺少的就是上面的那个期望行为,以及需要按“tab”键才能将焦点移到文本编辑框中。</P>
回复:快速显示与正则表达式匹配的行子集的数据视图它可能在某个时候开始变慢,你应该添加一个检查,确保只选择了字符列,但你可以构建表达式来创建连接
Names Default To Here(1);
dt = Open("$SAMPLE_DATA/Big Class.jmp");
dt << Select Columns({:name, :sex});
rgx_patter = "EF";
cols = dt << Get Selected Columns("String");
conc_expr = Expr(Concat());
For Each({colname}, cols,
Insert Into(conc_expr, Name Expr(As Column(dt, colname)));
);
regex_expr = Substitute(
Expr(!Is Missing(Regex(_conc_expr_, _rgx_pattern_, "\0", IGNORECASE))),
Expr(_conc_expr_), Name Expr(conc_expr),
Expr(_rgx_pattern_), rgx_pattern
);
rows_of_interest = dt << Get Rows Where(regex_expr);
回复:快速显示与正则表达式匹配的行子集的数据视图您还可以使用模态窗口强制将焦点放在窗口中,但这对用户体验来说可能非常糟糕。
回复:快速显示与正则表达式匹配的行子集的数据视图就在我以为自己开始明白的时候……
文档里说 Expr() “返回未求值的参数”——说实话,这对我来说毫无意义。听起来它只是返回你传入的值而已。
在你之前的代码中,它看起来像一个子程序,当时还挺合理的。但现在我看到的是 Expr(Concat()),我搞不清楚到底连接了什么。之后,你用 Insert Into() 把 Expr() 对象插入进去——但是 JMP 怎么知道把值插入到哪里呢?就连 ChatGPT 也没能帮我理解。
这感觉就像试图通过复制手部动作来重现魔术师的魔术一样令人沮丧,特别是因为 Get Row() 的文档似乎完全承诺了我想要的行为。
当然,这一切都不是你的错,我非常感谢你的帮助。我觉得我现在的配置应该足够好了。谢谢!
回复:快速显示与正则表达式匹配的行子集的数据视图这里没有连接任何内容。Expr(Concat()) 函数。在这种情况下,您可以将其视为参数的收集器,这些参数将在表达式构建完成后进行连接。您也可以先使用列表构建它,然后用 concat 函数替换列表。
Names Default To Here(1);
dt = open("$SAMPLE_DATA/Big Class.jmp");
val1 = "name";
val2 = "sex";
c = {};
Insert Into(c, Name Expr(As Column(dt, val1)));
Insert Into(c, Name Expr(As Column(dt, val2)));
show(c);
Substitute Into(c, Expr(List()), Expr(Concat()));
Show(c);
// Example use
Eval(EvalExpr(
dt << New Column("Concat", Character, Nominal, Formula(
Expr(Name Expr(c))
));
));
回复:快速显示与正则表达式匹配的行子集的数据视图好的,我想我已经弄明白了——这个脚本基本上是 unix/linux/mac“egrep”命令的表格等价物,即选择/显示仅与用户输入的正则表达式(搜索字符串)匹配的行:
Names Default To Here( 1 );
If(
ex = New Window( "Enter search regex",
<
<MODAL></MODAL>
<P>所有按钮都能正常工作,即使处理数千行数据也相当快。我个人把它做成了一个插件,绑定到 cmd-shift-e(egrep)上,现在一直在用。当然,我乐意听取改进建议。希望这能帮到大家!</P> <BR /> <P>(非常感谢<A href="https://community.jmp.com/t5/user/viewprofilepage/user-id/14366" target="_blank">@jthi</A>的耐心和洞察力!)</P>
回复:快速显示与正则表达式匹配的行子集的数据视图看起来不错!我想做一些小改动:
- 打开新窗口之前,请检查是否有打开的表,如果没有,则运行 stop();
- 如果没有匹配,最后一行会抛出错误。您可以检查选中的行数,如果为 0 则使用 stop() ,或者向用户显示没有匹配的信息。
- << 获取行数 最有可能比 << 选择行数 更快
- << 如果您希望在第一个正则表达式没有任何匹配项时让用户输入新的正则表达式,也可以使用 On Validate
查看更多...
Names Default To Here(1);
If(N Table() == 0,
stop(); // display error message to user if necessary
);
dt = Current Data Table();
nw = New Window("Enter search regex",
<
<MODAL>
0, col = selCols[1]; , col = Column(dt, 1) << get name; ); selrows = Eval(EvalExpr( dt << Get Rows Where(!Is Missing(Regex(Expr(NameExpr(As Column(dt, col))), inputRegex, "1", IGNORECASE))); )); If(N Rows(selrows) == 0, stop(); // display error message if necessary, this could also be done already within modal window (<< On Validate), if you wish to let user perform new search ); dt2 = dt << Subset(Rows(selrows), Selected Columns(0), Link to original data table(1), Output Table("")); // dt2 << Select Rows(1::NRows(dt2)); // to select rows if necessary
</MODAL>