挑战
创建一个程序,该程序在Microsoft Windows上运行时返回真实值(为简单起见,我们将坚持使用Windows 7、8.1和10),而在任何其他操作系统(OSX,FreeBSD,Linux)上运行时则返回假值。
规则
- 无法在平台上运行/编译的代码不算作假值。
获奖标准
我将其标记为code-golf,因此得分最低者获胜,但是我也非常有兴趣看到针对该问题的创造性解决方案。
创建一个程序,该程序在Microsoft Windows上运行时返回真实值(为简单起见,我们将坚持使用Windows 7、8.1和10),而在任何其他操作系统(OSX,FreeBSD,Linux)上运行时则返回假值。
我将其标记为code-golf,因此得分最低者获胜,但是我也非常有兴趣看到针对该问题的创造性解决方案。
Answers:
<C-a>1
在Windows上,<C-a>默认情况下(ctrl + a)映射到Select All。如果您1在Windows中以选择模式键入内容,它将用您键入的内容(1)替换选择内容,并在缓冲区中保留1。
在其他操作系统上,<C-a>默认情况下映射到Increment number。因为没有要增加的数字,所以它是无操作的,然后1会增加计数,但就缓冲区而言是无操作的。
1在Vim中是真实的,空字符串是虚假的
Ctrl + a,1。如果是,Ctrl + a + 1则将其计为1次击键。
ispc
从文档中:
tf = ispc如果MATLAB®软件的版本适用于Microsoft®Windows®平台,则返回逻辑1(真)。否则,它返回逻辑0(假)。
还有功能ismac和isunix。我将它留给读者了解这些功能的作用。 Mego恳求提供图表说明ismac,isunix因此我尝试在此处进行说明:
这不是要了一个图ispc,但我可以透露的是,行为非常相似,不同的是用OSX并Unix用Windows。
第二种方法:
这是getenv使用23个字节的第二种方法,该方法应该是防弹的,除非另有另一个操作系统开头W:
x=getenv('OS');x(1)==87
getenv 'name'在底层操作系统环境列表中搜索形式为的文本name=value,其中name是输入字符向量。如果找到,MATLAB®将返回字符向量值。如果找不到指定的名称,则返回一个空矩阵。
import os
0/('['>os.sep)
感谢FlipTack提供了3个字节
该程序利用Windows是唯一\用作路径分隔符的操作系统这一事实。通常这是令人沮丧和糟糕的,但实际上这是一次优势。在Windows上,它'['>os.sep为false,然后0/0进行计算,从而导致a ZeroDivisionError并以非零的退出代码退出。在非Windows平台上,'['>os.sep为true,则使表达式0/1不执行任何操作,并且程序以退出代码0退出。
31 DB 89 D8 40 CD 80
要么
xor ebx, ebx
mov eax, ebx
inc eax
int 0x80
首先,我们将设置eax到1(系统调用号exit(int val)为Linux,FreeBSD和OSX)。然后,我们将调用中断门0x80这是系统调用门Linux,FreeBSD和OSX。这将导致程序退出,其状态ebx为0(false)。
在Windows上int 0x80是无效的门(它2e用作syscall门),并且会使程序崩溃,导致其以正退出代码(true)结尾。
编辑:将无法进行,OSX因为它在32位上(通过堆栈)具有不同的参数传递约定。
FreeBSD - System Calls:有关中的系统调用的信息FreeBSD。System calls in the Linux kernel. Part 2.:有关Linux系统调用的精彩文章。Linux Syscall Reference:的系统电话号码参考Linux。Windows Syscall Shellcode:有关windows从程序集中直接调用系统调用的文章。Making system calls from Assembly in Mac OS X:有关系统调用的文章OSX。xor eax, eax在那里?
false以代码1 true退出,而代码0退出)。
eax并且ebx在程序启动时(在非Windows操作系统上)清零,如果我没有记错的话,这不能保证。它还明确地假定Linux的syscall参数传递约定与FreeBSD和OSX的传递约定相匹配,这确实非常令人惊讶。
mov eax, 1会被转换为\xB8\x01\x00\x00\x00,只需移动寄存器并调用就会更长inc。
感谢@Downgoat一个字节!划掉44仍然是常规44
感谢@Neil提供了两个字节!
f(){return
#ifdef WIN32
!
#endif
0;}
0out移出ifdef并更改为1to 来节省一堆字节!,但是我认为_WIN32+0效果更好。
return 1;在ifdef内,然后删除else,因为c99中不返回的main必须返回
#if WIN32。在非Windows上,由于未定义WIN32,因此需要预处理器将其视为
`<?=PATH_SEPARATOR>":";`
1如果路径分隔符为分号(对于DOS和OS / 2除外的所有其他OS,则为冒号或空),则打印,否则输出。
也是22个字节,但不是那么安全:
<?=strpos(__FILE__,92);
如果文件路径包含反斜杠,则输出正整数;否则没有。
一个安全的替代方案,有27个字节:<?=DIRECTORY_SEPARATOR>"/";打印1或不打印。
一个奇怪的发现:<?=__FILE__[1]==":";(20个字节)是应该的,没有任何安全的,但确定。但是,尽管__FILE__假装为字符串(我尝试过var_dump和gettype),但对其进行索引会引发错误,除非您将其复制到其他位置(连接也可以)或将其用作函数参数。
编辑:(
<?=(__FILE__)[1]==":";也为22个字节)在PHP 7中工作;但这是因为括号将常量的值复制到一个临时变量。
27个字节:<?=stripos(PHP_OS,win)===0;
测试预定义PHP_OS常量是否以win(不区分大小写; Windows,WIN32,WINNT,但不包括CYGWIN或Darwin)开头;1为Windows 打印,否则为空。
17/18字节:
<?=strlen("
")-1;
打印1是否与Windows换行符一起存储(也在DOS,OS / 2和Atari TOS上存储-尽管我怀疑有人曾经为TOS编译过PHP),否则进行打印0。
您还可以检查常数PHP_EOL。
更多选择:
PHP_SHLIB_SUFFIX是dll在Windows上,但不一定只有在那里。
php_uname()返回有关操作系统等的信息;从WindowsWindows 开始。在Windows的浏览器中调用时
$_SERVER['HTTP_USER_AGENT']将包含Windows。
<?=defined(PHP_WINDOWS_VERSION_BUILD);(38个字节)在PHP> = 5.3中有效
结论
判断它是否真的是Windows而不是看起来像Windows的唯一故障保护方法似乎是检查操作系统名称。对于PHP:php_os()出于安全原因可能被禁用;但PHP_OS可能始终包含所需的信息。
<?=class_exists(COM);。COM据我所知,该类仅在Windows下可用。那应该为您节省一个字节。
$OperatingSystem=="Windows"&
&东西,它将不会打印任何内容(因此它也不是可调用函数) ,但仅是代码段/表达式)。
Out[1]= False输出:~/opt/Mathematica/11.0/Executables/math <<< '$OperatingSystem=="Windows"'
特别感谢separatorCharOlivierGrégoire的建议,以及Kritixi Lithos的-1个字节!
这是一个lambda表达式,它返回一个布尔值。可以将其分配给Supplier<Boolean> f = ...;并调用f.get()。
()->java.io.File.separatorChar>90
在线尝试!-服务器不是Windows,因此会打印false。但是,在我的Windows计算机中,将打印相同的代码true。
该代码的作用是获取系统的文件分隔符,并检查其代码点是否大于character [。对于Windows,这是正确的,因为它\用作分隔符-但其他所有操作系统都使用/,在ASCII表中具有较低的代码。
()->java.io.File.separatorChar=='\\'只有36个字节。
()->java.io.File.separatorChar>'['!
6=9!:12
这是一个动词(类似于一个函数),它使用内置的外部连词9!:12来获取系统类型,其中5是Unix,而6是Windows32。
.Platform$O>"v"
感谢plannapus建议使用部分匹配进行列表元素提取。
.Platform是一个列表,其中包含构建R的平台的一些详细信息。有一个元素OS.type(唯一的名称以“ O”开头的元素)是字符串,给出了计算机的操作系统(家族)。其中一个"unix"或"windows"。
所以"unix"少了"v",但"windows"更大了"v"。其他有效的15个字节的答案是
.Platform$O>"V"
.Platform$O>"w"
.Platform$O>"W"
R为正在为操作系统的类Unix,Windows和Mac家庭发展。不支持其他OS系列。
print$^O=~MS
^O 应该用文字Control-O代替。
1在Windows上输出,在另一个OS上没有输出。
请注意,我没有使用say它,因为它添加了结尾的换行符,这在Perl中是正确的。
-2个字节,感谢primo。(和已解决的潜在问题)
由于使用了ais523,因此为-1个字节。
^O。
$^O=~W尽管没有必要使用正则表达式定界符,但我可能会反对MS。另外,您也可以匹配$^X=~':'。
W它,所以我假定检查的W精细..为什么你提出任何理由MS呢?
40 39 04 24 75 02 CD 80 C3
编译自:
inc eax ; set eax to 1
cmp [esp], eax ; check if [esp] == 1 (linux)
jne windows ; jump over "int 0x80" if on windows
int 0x80 ; exit with exit code 0 (ebx)
windows:
ret ; exit with exit code 1 (eax)
inc eax和来使代码更短int 0x80,我认为它应该在Windows上失败并终止进程。
console.log((
//Begin
_=>navigator.oscpu[0]>'V'
//End
)())
经过Firefox测试。(Chrome没有该oscpu属性。)由于小写字母的字符代码比大写字母的字符代码高,因此这取决于Firefox支持的任何平台上的首字母为navigator.oscpu大写而不是W,X,Y或Z(除了Windows,当然)。根据这篇文章,情况就是这样。
oscpu可能navigator是您可以使用的最短属性。另外,测试一个正则表达式可能会更短一些,但是我还没有测量它。
!=-1并在~右边的箭头后面添加一个右箭头,以节省3个字节。
navigator.oscpu>'V'可能工作以及
()=>(int)System.Environment.OSVersion.Platform<4
感谢TheLethalCoder,节省了13个字节
或83字节的完整程序:
class P{static int Main(){return(int)System.Environment.OSVersion.Platform<4?1:0;}}
在Microsoft .NET实现中,各种Windows变体都使用枚举值0到3 。4是Unix,5是Xbox [360](我不会考虑“ Windows”),6是MacOSX。Mono使用相同的值,在早期版本的Unix / Linux中增加128。
因此,所有<4的都是Windows,其他所有的都不是Windows。
int?
CS0019 Operator '<' cannot be applied to operands of type 'PlatformID' and 'int'基本上,C#的输入规则说我不能直接比较a PlatformID和int直接,也没有从PlatformIDto 隐式转换int。但是,是一个明确的从所有枚举投给他们的价值观,这是我拿的优势在这里...
System.Environment.OSVersion在所有。如果您对此有疑问,则还应该删除所有其他非UWP答案。事实证明,您不能(当前)在非Windows平台上运行UWP应用,因此您也可以删除所有这些。剩下0个答案和一个无法回答的问题。
Action<bool>在第一个示例中将其编译为48字节(我尚未测试过,但相信它可以工作)_=>(int)System.Environment.OSVersion.Platform<4;,()=>...尽管它可能需要49字节
Funcs和Actions的匿名函数。我相信它在“高尔夫技巧”页面中,并且我几乎一直都在使用它们。另外,匿名函数在其他语言中也大量使用,因此我认为在这里使用它们是安全的
@if %OS%==Windows_NT if not exist Z:\bin\sh echo 1
编辑:固定为忽略DOS,而不是声称它是Windows。
我知道在Windows外部运行Batch 的唯一其他方法是使用WINE,默认情况下它将映射Z:到/。因此,如果Z:\bin\sh存在,则可能是/bin/sh,而不是MS Windows。
我不知道WINE将%OS%设置为什么,但是如果不是,Windows_NT那么我可以节省23个字节。
OS=Windows_NT
?INSTR(ENVIRON$("COMSPEC"),"W")
在Windows下输出非零,在其他所有条件下输出0。
COMSPEC是Microsoft操作系统特有的环境变量。它指向命令解释器,通常为command.com或cmd.exe。在Windows下,命令解释器位于Windows目录中的某个位置。在MS-DOS下,它位于DOS目录中或磁盘的根目录上,而在任何其他OS下,它都不存在。
通过检查的值是否COMSPEC包含“ W”,我们可以判断Windows与非Windows之间的区别。
感谢@Patrick,他使用Node的REPL将我的解决方案节省了 12个字节:
_=>os.EOL>`
`
原始解决方案:
_=>require('path').sep!='/'
Node.js REPL,则只需使用_=>path.sep!='/'
node在控制台上输入时运行的程序。从那里开始,所有系统节点模块都可以使用,而无需require()它们。
!=到>自ASCII指数\ 为92,并/为47
立即窗口函数,返回true如果系统的OS代码开始比3的长度更长,因为信息被限制为输出或者其他mac或pcdos该返回true仅在Windows PC上
?[Len(Info("SYSTEM"))>3]
之前的版本
''# Ignore the second `"` that follows every `\` - its only there for highlighting
?Left(Environ("OS"),1)="W" # 24 Bytes
?InStr(ThisWorkbook.Path,"\"") # 29 Bytes
?Mid(ThisWorkbook.Path,3,1)="\"" # 30 Bytes, Restricted to local Files
?Application.PathSeparator="\"" # 30 Bytes
?Left(Application.OperatingSystem,1)="W" # 40 Bytes
变化
-1感谢Neil使用Left(...,1)了Mid(...,1,1)
-10感谢ChrisH指出@Mego 的Path Separator Trick
-1对于检查WorkbookPath的"\" ,而不是使用Application.Path Separator
-4切换到 Environ()
-2用于切换到 [Len(Info(...
新颖的解决方案,51字节
通过条件编译的方法将新的sub例程输出到VBE立即窗口,1 (truthy)在Windows 0 (falsey)下和在Mac下。
Sub a
i=1
#If Mac Then
i=0
#End If
Debug.?i
End Sub
left节省您一个字节。
?Application.PathSeparator)="\"由于是单个字符,因此为32)
'W'∊∊#⎕WG'APLVersion'
#⎕WG'APLVersion' 根(#)W indow G et property APL版本
∊ 征募(拼合)
'W'∊ 是W¯¯一员?(非Windows返回值不包含大写字母W)
如果是Windows,则以下内容将输出1,否则将不输出任何内容。忽略字符串转换的通知。
<?=PHP_OS==WINNT;
在线尝试 Linux在线测试,因为沙箱是用于PoC的Linux。
>V可能也可以。
()->System.getenv().get("OS").contains("Windows")
比其他Java回答更长,但是采用了不同的方法。
此lambda符合,Supplier<Boolean>可以通过以下程序进行测试:
public class DetectMSWindows {
public static void main(String[] args) {
System.out.println(f(() -> System.getenv().get("OS").contains("Windows")));
}
private static boolean f(java.util.function.Supplier<Boolean> s) {
return s.get();
}
}
.contains("W")呢?
import System.Info
f=os!!0=='m'
我检查“ m”的第一个字母输出,对于Windows,应为“ mingw”。据我所知,没有其他以M开头的操作系统。该信息来自https://github.com/ghc/ghc/blob/master/compiler/utils/Platform.hs
os给出"mingw32"。
rm $0
也可以在大多数其他POSIXy shell中使用。(请注意,存在Windows bash和的Windows端口rm;即使通常仅在更重的POSIXy操作系统上使用它们,也不是完全虚空的条目。)通过退出代码输出(0 =否,1 =正确)。如果允许使用文件名(例如rm a),则可以算作4个字节。请注意,在文件名非常奇怪的情况下,这可能会失败(rm由于缺少引号而将其解释为自变量,并且可能会删除您关心的文件,因此,建议不要从名称奇怪的文件中运行该程序)。
注意:从磁盘上删除程序是有副作用的,或者至少是尝试这样做。如果我们在Windows上运行,则操作系统将无法删除正在运行的文件(Windows不允许该操作默认或完全停止),因此rm将出错。bash捕获错误并将其转换为退出代码(因此该程序作为一个整体正常终止)。这里的其他大多数条目在退出代码中都使用0代表虚假,使用1代表真实,因此也是如此。请注意,bash' if语句根本不接受整数(而是根据命令和分支是否成功运行来接受命令和分支,并且算术测试是通过诸如test会故意在比较失败时报告“崩溃”),因此,在合法性方面,这比通过退出代码输出的程序(在if语句测试中0为有效的语言,并将其发送到else分支)的合法性更高。
os 1- not .
true在Windows,falseLinux和macOS上打印。8th支持的其他平台是Android,iOS和Raspberry Pi,但我无法对其进行测试。
非高尔夫版本(带注释)
G:os \ Return a number n indicating the operating system
\ 0 for Linux
\ 1 for Windows
\ 2 for macOS
\ 3 for Android
\ 4 for iOS
\ 5 for Raspberry Pi
n:1- \ Subtract 1
G:not \ If Windows --> true, otherwise --> false
. \ Print result
America is great.
如果在Windows上运行,此程序将打印:
The big problem this country has is being PC
这被认为是真实值。
空输出和以下值是虚假的:
Boycott all Apple products until such time as Apple gives cellphone info to authorities regarding radical Islamic terrorist couple from Cal
空输出将出现在任何linux系统上(对于该程序),长苹果响应显然发生在Mac上(对于任何程序)。在TIO上,后端(我假设)是Unix操作系统,因此您只能得到虚假的值。在我的计算机上,我收到PC消息。
不能100%确定这是否算作错误消息(这将使答案无效),但是如果您不知道这件事,可能值得您大笑。