挑战
创建一个程序,该程序在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;}
0
out移出ifdef
并更改为1
to 来节省一堆字节!
,但是我认为_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()
返回有关操作系统等的信息;从Windows
Windows 开始。在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"'
特别感谢separatorChar
OlivierGré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
直接,也没有从PlatformID
to 隐式转换int
。但是,是一个明确的从所有枚举投给他们的价值观,这是我拿的优势在这里...
System.Environment.OSVersion
在所有。如果您对此有疑问,则还应该删除所有其他非UWP答案。事实证明,您不能(当前)在非Windows平台上运行UWP应用,因此您也可以删除所有这些。剩下0个答案和一个无法回答的问题。
Action<bool>
在第一个示例中将其编译为48字节(我尚未测试过,但相信它可以工作)_=>(int)System.Environment.OSVersion.Platform<4;
,()=>...
尽管它可能需要49字节
Func
s和Action
s的匿名函数。我相信它在“高尔夫技巧”页面中,并且我几乎一直都在使用它们。另外,匿名函数在其他语言中也大量使用,因此我认为在这里使用它们是安全的
@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,false
Linux和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%确定这是否算作错误消息(这将使答案无效),但是如果您不知道这件事,可能值得您大笑。