C PHP JavaScript Python3 Bash

Basic
📦 Package Manager ? composer
下载composer.phar
sudo mv composer.phar /usr/local/bin/composer
npm
npm install some_garbage
pip -
🔍📦 Search Packages ? packagist.org npmjs pypi
📄 Package Configure File ? composer.json package.json -
Create Configure File ? Automatic generate when install package npm init (-y) -
🔩 Install Package By Configure file ? php composer.phar install
sudo composer install
npm install | npm i -
🔩 Install Package ? php composer.phar require geoip2/geoip2:~2.0
or composer require geoip2/geoip2
npm i vue
npm i -g typescript typescript 强调type,类型检查
-g: Global
--save-dev或-D 开发时依赖
--save(默认) 生产环境运行时依赖


npm uninstall vue
npm update vue
(linux)sudo pip install pymysql
(win)python -m pip install pymysql
Print Version gcc -v composer -V node -v
npm -v
vue -V
python3 -V
python3 -m pip -V
Upgrade Package Manager ? composer self-update
npm install npm -g
(linux)sudo pip install -U pip
(win)python -m pip install -U pip
块分隔符 { } { } { } 用缩进 if关闭fi do关闭done
语句分隔符 ; ; newline ; newline newline ;
单行注释 // comment // comment // comment # comment # comment
多行注释 /* comment line
another line */
/* comment line
another line */
/* comment line
another line */
"""
comment line
another line
"""
-
资源(组件/模块)引用
include, import, require, source...
#include <stdio.h> include|include_once|require|require_once
include 和 require 语句是相同的,除了失败:
require将产生致命错误 (E_COMPILE_ERROR) 并停止脚本
include只会产生警告(E_WARNING)并且脚本会继续
获取指定文件中的代码,并将其复制到使用 include 语句的文件中(代码拼接,没独立作用域)
_once 表示只拼接一次,再次引用忽略
spl_autoload_register
注册自动加载函数,在使用未定义的类时触发自动加载,不再需要写include了
<script type="text/javascript" src="1.js"></script>

模块化开发Demo
<script type="module" src="m.js"></script> 浏览器对于带有 type="module" 的 script,都是异步加载

<script type="module">
import { a, funca } from "./mymodule.js"
funca();
</script> A web-page opened via the file:// protocol cannot use import / export.
import math # math.py脚本
math.pi
from math import pi,ceil #可以只导入pi或某些函数
pi #3.141592653589793
ceil(2.4) #3
Python的import并非像php include, 查看wiki
source other.sh
Namespace
组织代码和避免命名冲突的技术
- namespace GeoIp2\Database;
...
class Reader implements ProviderInterface {}
function Myfun() {}
const MY_CONSTANT = 12;
没有命名空间概念,可使用模块化的方式来实现类似的效果。每个模块都是一个独立的作用域

// MyNamespace.js
module.exports = MyNamespace
没有命名空间概念,Module实现命名空间效果

# mymodule.py
myvar = 12
def myfunc():
-
使用命名空间 - use GeoIp2\Database\Reader;
use function GeoIp2\Database\Myfun;
use const GeoIp2\Database\MY_CONSTANT;
$reader = new Reader('xx');
Myfun();
echo MY_CONSTANT;
const MyNamespace = require('./MyNamespace')
MyNamespace.myFunction()
import mymodule
print(mymodule.myvar)
mymodule.myfunc()
Value & Type
命名 区分大小写,可使用中文命名 变量常量名区分大小写,函数class名不区分,变量需$开头,可使用中文命名,比如 $数量=300 区分大小写,可使用中文命名 区分大小写,可使用中文命名 区分大小写,不可使用中文命名
基础数据类型 int i = 1; // 2 或 4 bytes 65536-4294967296
i = 2;
float f; // 4 bytes
f = 5.99;
double lf = 5.99; // 8 bytes
char c = 'M'; // 1 bytes

printf("%d-%f-%lf-%c\n", i, f, lf, c); // 2-5.990000-5.990000-M
printf("%d-%.2f-%.2lf-%c\n", i, f, lf, c); // 2-5.99-5.99-M
printf("%p-%p-%p-%p\n", &i, &f, &lf, &c); // 0x7ff7b3d0161c-0x7ff7b3d01618-0x7ff7b3d01610-0x7ff7b3d0160f
printf("%lu-%lu-%lu-%lu\n", sizeof(i), sizeof(f), sizeof(lf), sizeof(c)); // 4-4-8-1 单位bytes
基本格式说明符:对于int %d和%i都行,%p 打印内存地址, %s 用来打印字符串
int* p_i = &i;
bool b = false


隐式/显式类型转换
float f = 8; // 隐式类型转换 编译器自动将8 转化为 8.000000
float r = 5 / 2;
printf("%f", r); // 2.000000 ,因为5 和 2 是int,5 / 2 结果也是int 为2,float隐式类型转换成2.000000
float r2 = (float) 5 / 2; // 显示类型转换 int to float
printf("%f", r2); // 2.00000
整型
$i = 1;
浮点型
$f = 1.234
string
$str = '';
Boolean
$b = FALSE;
null
$v = NULL;
Object
$bar = new foo;
number型
var x = 0; // typeof(x)的值是"number"
BigInt型
String(BigInt(1)+BigInt(Math.pow(2,53)))
string型
var str = "";
boolean型
var b=false;
undefined型
var a = undefined
object型
var car = null; // typeof(car)的值是"object",null值是一个空的对象指针
var obj = {}; // 同= new Object();typeof值object
var arr = []; // 同= new Array(); typeof值object
var re=/regexp/g; // typeof值Object 同= new RegExp("regexp","模式修饰符g全局模式应用所有字符串,i区分大小写,m多行匹配")
var foo = function() {} // typeof值function

引用(reference)值分配给变量时,空间需要在堆(heap)上分配, 引用值不能像原始(primitive)值直接分配在栈(stack)上,因为它没有固定的尺寸,所以它将内存地址存在栈上, 作为一个指针

TypeScript
let isDone: boolean = false
let list: number[] = [1, 2, 3] // 数组
let list: Array<number> = [1, 2, 3] // 数组另一种表达
let x: [string, number] = ['s', 9]// 元组
enum Status { enable, disable } let s = Status.enable
number型
x=0
string型
str=""
Boolean型
b = True # True/False
空型
None
Object型
Ferrari458 = Car('Ferrari',570)
bash中的所有变量都是string,无论有没有加引号

有些变量被shell环境和OS环境来存储一些特殊的值,叫环境变量
echo $PWD
还有PATH,USER,SHELL,HOME,UID(root为0)等常用环境变量
数据类型判断 - echo gettype("mark"); // string typeof value==="undefined"

var theHobbit = new Book('07122-4', 'The Hobbit', 'J. R. R. Tolkein');
theHobbit instanceof Book; //值为true, 某类的实例
print(type(value))

print(isinstance(12, int)) # True
print(isinstance('hi', str))
print(isinstance([1,2], list))
都是string
🌍 作用域 PHP是文件拼接 文件之间不是独立作用域
函数内不能读函数外的非全局变量

global关键字可实现在函数内使用外部变量
$a=1;
function b() {
  global $a;
  echo $a;
}
b();

超全局变量$GLOBALS
$GLOBALS['a'] = 1;
超全局变量还有$_SESSION $_SERVER $_GET $_POST $_REQUEST $_FILES $_COOKIE $_ENV
var申明, 都是全局的
window/self/globalThis
(browser);
self/globalThis
(web worker);
global/globalThis(Node.js)
myglobal="hello";
myglobal; // 值为hello
this.myglobal; // 值为hello
window.myglobal // 值为hello

var局部变量,函数内可以沿着作用域链调用外层变量

let, const设置的变量/常量可限制在块级作用域内使用
块级作用域围墙有{} | while(){} | if(){} | try{} catch(e){}| for(let i=0;i<10;i++){ 每一个循环都是一个作用域 }
var a = []
for (let i = 0; i < 10; i++) {
  a[i] = function () { console.log(i); };
}
a[6](); // output: 6 如果上面的let 改成var 他的结果就是10
如果没有let 怎么办 -->值变参分割变量作用域
for (var i = 0; i < 10; i++) {
  (function(i) {
    a[i] = function () { console.log(i); }
  })(i)
}
执行上下文
local(默认): 局部变量
nonlocal: 非局部变量,用于闭包
global: 全局变量
没有作用域,函数内外可互相访问
a="好"
function display(){
  b='玩'
  echo $a
}
display # 好
echo $b # 玩
闭包(closure)
闭包就是能够读取其他函数内部变量的函数
- 使用 use 关键词
function counter()
{
  $i = 0;
  return function () use (&$i) {
    return ++$i."\n";
   }
}

$nays = counter()
echo $nays()
echo $nays()
var counter = function () {
   var i=0;
   return function () {
      return ++i;
   };
};
var nays = counter();
console.log(nays()); // output: 1
console.log(nays()); // output: 2
def counter():
  i=0
  def foo():
    nonlocal i # 申明非局部变量
    i += 1
    return i
  return foo
nays = counter()
print(nays()) # output: 1
print(nays()) # output: 2
内存回收♻️ 手动回收
malloc calloc等申请内存
free 释放内存
自动回收
以前引用计数(无法解决循环引用) 现在标记清除
自动回收
以前引用计数(无法解决循环引用) 现标记清除+碎片🧩 整理
自动回收
先引用计数,定期标记清除(循环引用) 两种结合
判断变量是否存在 if(!empty($v)){}//null 或未定义或''或0 或FALSE 为TRUE
if(is_null($v)){}//null 或未定义为TRUE
if (isset($v)) {}// 非null或已定义为TRUE
if(typeof(var_name)=='undefined') {
  //不存在
}
a='mark'
print('a' in globals()) # True
print('a' in locals()) # True
print('b' in globals()) # False
if [ ! -n "$1" ]; then # 变量是否存在
获取资源类型 get_resource_type() - --
变量的变量 $a='hello';
$$a='world';
echo ${$a}; //等同于echo $hello;
---
const
常量是在程序运行时不会被修改的量
用大写字母是很好的做法
const float PI = 3.1416; define定义的常量可跨脚本跨函数
define("PI", 3.14); // define()在函数里定义的常量在外面依然可使用
const PI='3.1416'; //const定义的必须处于最顶端的作用区域
const PI = 3.1416;
PI = 3; // TypeError: Assignment to constant variable.
const foo;
// Uncaught SyntaxError: Missing initializer in const declaration
if (true) { const MAX = 5; }
console.log(MAX) // Uncaught ReferenceError: MAX is not defined const的作用域与let相同,只在声明所在的块级作用域内有效
const a = {}; a.a = 1; 对象的属性能改变,const只能保证这个指针是固定的
没有常量 -
enum
通常用来表示如color, type, status等数目有限、形式离散、表达明确的量
enum Level {
  LOW,
  MEDIUM,
  HIGH
};
enum Level myVar = MEDIUM;
printf("%d", myVar); // 1
enum LogLevel { ERROR, WARN, INFO, DEBUG, } -
set value $v = 1;$a=$b=3;var v = 1;var a=b=3
建议使用下面的single var模式
a=1;b=c=3myname=mark 注意等号=两边不能有空格,不然会被当成命令,如果值中间有空格就要加引号如"mark li"
echo $myname echo 后面的字符中有空格可以不加引号
并行set value list($y,$z)=array(2,3); //把数组中的值赋给一些变量 var x=1,y=2,z=3

字符串解构赋值
let [a, b, , c, d] = 'abcde'; // d == 'e'
数组解构赋值
let [, b, c] = [1, 2, 3]; // c == 3
Set数据解构赋值
let[a,,c]=new Set([1,2,3]); // c == 3
对象解构赋值
let {x,y} = {z:2,y:3,x:4} // x == 4 y == 3
属性的解构赋值
let {length : len} = 'hello'; // len == 5
let [head, ...tail] = [1, 2, 3, 4];// tail=>[2,3,4]
a, b = b, a+b
它不等于a=b;b=a+b或b=a+b;a=b
-
🤹‍♀️swap list($x, $y) = array($y, $x); var temp=a
a=b
b=temp
[a,b]=[b,a];
- -
Proxy 拦截 ? ? 拦截对象 getter setter
flashvim = {}
Object.defineProperties(flashvim, {
  cmd: {
    configurable: true,
    get() {
      console.log('拦截读值')
      return cmd
    },
    set(newval) {
      cmd = newval
      console.log('拦截设值')
    }
  }
})
flashvim.cmd = 3 // 拦截设值

单个属性
Reflect.defineProperty(flashvim, "cmd", { configurable: true...
// Object.defineProperty 官方建议弃用

拦截对象 getter setter
flashvim = new Proxy({}, {
  get(target, key) {
    console.log('拦截取',key, '的值')
    return target[key]
  },
  set(target, key, newval) {
    console.log('拦截设', key, '的值', newval)
    return target[key] = newval
  }
})
flashvim.cmd = 3 // 拦截设 cmd 的值
拦截数组 getter setter
arr = [1,2,3]
proxyarr = new Proxy(arr, {
  get(target, key) {
    console.log('拦截取',key, '的值')
    return target[key]
  },
  set(target, key, newval) {
    console.log('拦截设', key, '的值', newval)
    return target[key] = newval
  }
})
proxyarr[3] = 4 // 拦截设 cmd 的值
? -
copy 默认深拷贝 原始值拷贝的是数据
数组/对象默认浅拷贝 -
数组/对象copy
线拷贝是拷贝指针

char str1[10] = "mark";
char str2[10];
strcpy(str2, str1);
printf("%s", str2);
$a = array(1,2,array(3,4));
$a2 =& $a; //浅拷贝
$a4 = $a; //深拷贝
引用值拷贝的是指针地址,所以两个对象指向相同的堆

var a = [1,2,[3,4]];
var a2=a; //浅拷贝
var a3=JSON.parse(JSON.stringify(a)) //深拷贝
a = [1,2,[3,4]]
b=a#地址拷贝
c=a.copy()#深拷贝
-
🧊 Freezes an object
- var day = ['Mon','Thu','Wed', 'Thu', 'Fri', 'Sat', 'Sun'];
var d = day;
Object.freeze(day);
d[0]='Monday';
console.log(day[0]); // output: Mon
console.log(d[0]); // output: Mon
frozenset() -
charCode 字符编码 char c = 'A';
printf("%d\n", (int) c); // 65

int i = 97;
printf("%c\n", (char) i); // a
String.fromCharCode(97) // 'a'
'A'.charCodeAt() // 65
Number and Operators
逻辑运算符
┏━━⁄ ━━━━🔋━┓ and ┗━━⁄ ━💡━━━━┛ ┏━⁄ ━┓ or ┣━⁄ ━┻━━━🔋━┓ ┗━━💡━━━━━━━┛ 电阻 ┏━⁄ ━━⬇━━━━┓ not ┣━━━━━▭━━🔋━┫ ┗━━💡━━━━━━━┛
&& || ! && || ! && || !
(1 && 2) === 2
(2 && 1) === 1
(1 && 0) === 0
(0 && 1) === 0
(0 && false) === 0
(false && 0) === false
(1 && 'm') === 'm'
(1 || 3) === 1
(0 || 3) === 3
(true || 3) === true
(false || 3) === 3
算术运算符 +-*/ 比较运算符 === 的优先级高于逻辑运算符所以带括号 ⚠️
(1 || 2 && 3) === 1
&& 优先级高于||
and or not if [ $env != "dev" ] && [ $env != "test" ];then
exit
fi

% echo 1 && echo 2
1
2
% echo 1 || echo 2
1
% echoo 1 || echo 2
command not found: echoo
2
% echoo 1 && echo 2
command not found: echoo
位运算符
按位与 按位或 按位异或 按位取反 101 101 101 &1100 |1100 ^1100 ~0101 ━━━━━ ━━━━━ ━━━━━ ━━━━━ 0100 1101 1001 1010 11111111 11111111 11111111 11111110 -2<<1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11111111 11111111 11111111 11111100 零填充左位移 -4 11111111 11111111 11111111 11111110 -2>>1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 11111111 11111111 11111111 11111111 有符号右位移 填充符号位(32位最左侧的一位,正数为0 负数为1) 11111111 11111111 11111111 11111110 -2>>>1 ━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━ 01111111 11111111 11111111 11111111 零填充右位移 -1
C 没有零填充右位移
printf("%d\n", 5 << 20); // 5242880 相当于5 * 2的20次方
printf("%d\n", -2 >> 0); // -2 即二进制-10
printf("%d\n", -2 >> 1); // -1
printf("%d\n", -2 >> 2); // -1
printf("%d\n", -2 << 1); // -4 即二进制-100; warning: shifting a negative signed value is undefined ;C 建议使用无符号整数unsigned int左位移
a&b a|b a^b ~a a<<b a>>b a>>>b
var CHUNK_SIZE = 5 << 20 // 5M,FF=256=8个0,1K=1024=10个0
1M=20个0,1M Bytes=2²⁰ 1Byte=8bits=2⁸种值=256



if (~'markbuild'.indexOf('mark')) {}
比较运算符
等于,不等于,大于,小于,不小于,不大于
== != > < >= <= == != > < >= <=
<>也可以表示不等于
== != > < >= <=
===全等(值和类型)
== != > < >= <= 对于数字 -eq -ne -gt -lt -ge -le
对于字符串 = 和 !=
算术运算符
加,减,乘,除,余数
+ - * / %
/ 没有类型转换
+ - * / %
/ 整除则是整数,否则小数
+ - * / %
/ 整除则是整数,否则小数
+ - * / %
/ 至少保留一位小数位
echo $[m+n]
+ - * / %
/整型
整除÷ int r = 13 / 5 (int) (13 / 5)parseInt(13/5)13//5 floor整除
divmod (除÷法的余数) int r = 10 / 3;
int remainder = 10 % 3;
$d=(int)(10/3);
$m=10%3;
d=(parseInt)(10/3);
m=10%3;
divmod(10,3)#输出(3,1)
赋值运算符
x=y,x=x+y,x=x-y,x=x*y,x=x/y,x="x""y",x=x%y
= += -= *= /= %= &= |= ^= >>= <<= = += -= *= /= .= %== += -= *= /= += %=同Javascipt
递增++递减-- ++x;
x++;
--x;
x--;
++x;
x++;
--x;
x--;
++x;
x++;
--x;
x--;
无,用+=1 $[--i]
$[i--]
let i++
乘方2⁴, 三次方根 ∛8 #include <math.h>

printf("%d\n", (int) pow(2, 4)); // 16 pow 的返回值是 double 类型的
printf("%lf\n", pow(8, (double) 1/3 )); // 2.000000
pow(2, 4)
pow(8, 1/3)
Math.pow(2,4)
Math.pow(8, 1/3)
2**4 #输出16
pow(2, 4)
pow(8, 1/3)
开方求平方根(二次方根) √ #include <math.h>

printf("%d\n", (int) sqrt(16)); // 4 sqrt 的返回值是 double 类型的
sqrt(4)Math.sqrt(4)import math
math.sqrt(4)
浮点转换
round四舍五入或银行家舍入法(奇进偶舍)
ceil(天花板)入
floor(地板)舍
printf("%f\n", ceil(1.1)); // 2.000000
printf("%f\n", floor(1.9)); // 1.000000
printf("%f\n", round(1.1)); // 1.000000
printf("%f\n", round(1.5)); // 2.000000 四舍五入
(int)$x
round($x) // 四舍五入
ceil($x)
floor($x)
Math.round(x) // 四舍五入
Math.ceil(x)
Math.floor(x) parseInt(x)
int(x)
round(x) // 奇进偶舍
math.floor(x + 0.5) // 四舍五入
round(5.5) == round(6.5) // True
import math
math.ceil(x)
math.floor(x)
保留 n 位小数 number_format(6, 1) (6).toFixed(1) // 6.0 返回字符串,toFixed 是 Number 类型的方法
最小值最大值 min(1, 2, 3);
max(1, 2, 3);
$a = array(1, 2, 3);
min($a);
max($a);
Math.min(1,2,3);
Math.max(1,2,3);
Math.min(...arr) // ES6
min(1, 2, 3);
max(1, 2, 3);
arr = [1, 2, 3];
min(arr);
max(arr);
绝对值 #include <math.h>
printf("%f\n", fabs(-4.2));

#include <stdlib.h>
printf("%d\n", abs(-4));
abs($x)Math.abs(x)abs(x) -
随机数 🎲 ⚀⚁⚂⚃⚄⚅ rand(0,99)Math.random()
0.0 ~ 1.0 之间的一个伪随机数
import random
random.random()
echo $((RANDOM % 100 +1))
echo $(jot -r 1 1 100) # jot 还可以生成随机字符串
进制转换
十进制与10根手指👐 有关
bindec('101')
hecdec('aa')
decbin(5)
dechex(170)
dec to hex/bin
Number(n).toString(16)
Number(n).toString(2)
hex/bin to dec
Number(0xaa)
Number('0xaa')
Number('0b101')
Number(0b101)
int('101', 2)
int('aa', 16)
bin(5)
hex(170)
-
String
字符串数据 char str[] = "don't say \"no\"";
char str2[] = {'d', 'o', 'n', '\'', 't', ' ', 's', 'a', 'y', ' ', '\"', 'n', 'o', '\"', '\0'}; // \0 指向null 代表字符串结束

┏━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━┳━━┓ ┃d┃o┃n┃'┃t┃ ┃s┃a┃y┃ ┃"┃n┃o┃"┃\0┃ ┗━┻━┻━┻━┻━┻━┻━┻━┻━┻━┻━┻━┻━┻━┻━━┛
$str = "don't say \"no\"";
echo 'don\'t say "no"';
str = "don't say \"no\"";
console.log('don\'t say "no"')
s = "don't say \"no\""
print('don\'t say "no"')
echo "hi,$var\!"
echo 'hi,mark!'
变量不能用于单引号中,!用不能直接用在双引号中
变量in字符串 - $count = 3;
$item = "ball";
echo "$count ${item}s\n";
const count=3
const item = "ball"
str = `${count} ${item}s`
str = String.raw `$(count) ${item}s`

`foo ${fn()} bar`// 函数in 字符串,`` 字符串支持换行
- echo "hi,$var\!"
格式化输出 printf("%s\n", str); echo sprintf("lorem %s %d %f","ipsum", 13, 3.7); - print('Hi, %s, you have $%d.' % ('Mark', 1000000)) printf "%-5s %-10s %-4.2f\n" 3 Mark 61.563
📐length #include <string.h>
char alphabet[] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
strlen(alphabet) // 26 字符串长度
sizeof(alphabet) // 27 bytes 字符串内存字节长度,多一个\0
char alphabet[50] = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
strlen(alphabet) // 26 字符串长度
sizeof(alphabet) // 50 bytes 字符串内存字节长度<
strlen("lorem") str.lengthlen(str) echo ${#varname}
get字符串中第n个字符 str[6]
*(str + 6)
$s[6] s[6]
s.charAt(6)
s[6]
s[-1] # 倒数第一个字符
s[6:-1] # 输出ipsu还有s[6:]和s[:-1}
echo ${a:5:1} # 第6个字符
set字符串中第n个字符 str[0] = 'D'
*(str + 0) = 'D';
$s = "bar";
$s[2]="z";
echo $s; //输出baz
s.slice(0, index) + 'z' + s.slice(index+1)
❌ s[0] = 'M' // JS 中字符串是不可变的(immutable)数据类型,一旦创建了一个字符串,就不能修改它的内容
Python 中的字符串是不可变对象,你不能直接修改字符串的某个字符。可以通过创建一个新的字符串来达到修改字符串的效果 -
字符串遍历 char str[] = "markbuild";

使用指针遍历
char* ptr = str;
while (*ptr != '\0') {
  printf("%c\n", *ptr);
  ptr++;
}

使用数组下标遍历
for (int i = 0; str[i] != '\0'; i++) {
  printf("%c\n", str[i]);
}

使用指针数组结合循环遍历
for (int i = 0; i < strlen(str); i++) {
  printf("%c\n", *(str + i));
}
for ($i = 0; $i < strlen($str); $i++) {
  echo $str[$i];
for (let char of 'foo') { for char in "mark":
  print(char)
-
字符串是否包含/在字符串中的位置 if(strpos('mark li', " ")===false)
右边字符串在左边字符串中首次出现的位置,没有返回false
注意有可能在第一个位置返回0
var st = "do re re";
if(st.indexOf("re") >= 0 )
// lastIndexOf()从未尾开始查找
"mark".includes("ar") // output: true
url.startsWith("https://markbuild.com")
location.hostname.endsWith('markbuild.com')
用正则的re.findall(r're',st) echo "$str" | grep -q "$substr"
if [ $? -eq 0 ]; then
  echo "包含子字符串"
else
  echo "不包含子字符串"
fi
合并字符串 #include <string.h>
char str1[20] = "mark"; // 预留足够的内存长度,否则illegal hardware instruction非法硬件指令
char str2[] = "build";
strcat(str1, str2);
printf("%s", str1);
$s2 = $s ."World!";
$s .= "World!";
s += 'World!'
s = s.concat('World')
'hello' + 'world'c=$a$b
repeat str_repeat(str, 3) 'oo'.repeat(2) // "oooo"3 * 'un' # ununun -
字符串定位切割子字符串
(slice,sub string)
substr("lorem ipsum", 6, 5)
第6+1个字符串起,往后切5个
str.slice(6,11)保留str[6]~str[11-1]
str.substr(6,5)官方不建议使用
s[6:11] str=mark.
echo ${str: -1} # 获得最后一个字符 显示. ⚠️注意空格
echo ${str: :-1} # 去掉最后一个字符 显示mark ⚠️注意空格
echo ${str:0:4} # 显示mark
echo ${str:4} # 显示.
全部大小写 strtoupper("lorem")
strtolower("LOREM")
"lorem".toUpperCase()
"LOREM".toLowerCase()
s.upper()
s.lower()
-
字符串首,单词首大写 ucfirst("lorem")
ucwords("lorem ipsum")
- s.capitalize()
s.title()
-
去掉两边的空格(默认),或其它字符(非串) trim(" lorem ")
ltrim("/category/page/5","/")
rtrim("12,4,6,",",") chop("12,4,6,",",")
" lorem ".trim()
.trimLeft() .trimStart()
.trimRight() .trimEnd()
" lorem ".strip() -
Reverse 🔁 echo strrev('mark');
// kram
str.split('').reverse().join('') print(str[::-1]) echo "mark"| rev # kram
数字转字符串 "value: ". 8String(num)
num.toString()
str(4) -
字符串转数字 7 + "12"
73.9 + ".037"
Number("73.9")int('4') -
[Array] 数组转字符串
┏━━━┳━━━┳━━━┓ ┃ do┃ re┃ mi┃ ┗━━━┻━━━┻━━━┛ ┏━━━━━━━━━━┓ ↵ ┃ do,re,mi ┃ ┗━━━━━━━━━━┛
$arr = array("do",re","mi","fa");
implode(",", $arr)
["do", "re", "mi", "fa"].join(",");
["do", "re", "mi", "fa"].toString(); // Output: "do,re,mi,fa"
lista=["do","re","mi","fa"]
s = ','.join(lista)
listb=[1,2,3]
s=','.join(str(i) for i in b)
[Array] 字符串转数组
┏━━━━━━━━━━┓ ┃ do,re,mi ┃ ┗━━━━━━━━━━┛ ┏━━━┳━━━┳━━━┓ ↵ ┃ do┃ re┃ mi┃ ┗━━━┻━━━┻━━━┛
explode(",","do,re,mi,fa")
\n是指换行符
var arr = "do,re,mi,fa".split(',');
// str.split(',',3) 只保留前3段
'm d   z'.split(/\s+/) // 支持正则字符
s="do,re,mi,fa"
arr=s.split(',')
list('123')
-
[Array] 字符串中每一个字符分割到数组
┏━━━━━━┓ ┃ abcd ┃ ┗━━━━━━┛ ┏━━━┳━━━┳━━━┳━━━┓ ↵ ┃ a ┃ b ┃ c ┃ d ┃ ┗━━━┻━━━┻━━━┻━━━┛
str_split("abcd")str.split('');l=list(s) -
非正则替换
echo str_replace('world', "sun", "hello world");
'hello world world'.replace('world', 'sun') // hello sun world
'hello world world'.replaceAll('world', 'sun')// hello sun sun
"hello world world".replace("world", "sun") # hello sun sun -
Regular Express 🧩
正则替换 $s = "do re mi mi mi";
$s2 = preg_replace('/mi/', "ma", $s);
var s="do re mi mi mi";
var s2=s.replace(/mi/g,"ma");
_val.replace(/([^<]+)<\/font>/g,"$1");
image2.replace(/\.([^.]+$)/,function($0) { return '_360x'+$0 })
s="do re mi mi mi"
re.sub(r'mi',r'ma',s)
sed '1,2s/mark/mk/' file # 替换1,2 行的第一个mark
sed '1,2s/mark/mk/g' file # 替换1,2行每行上的所有mark
sed -in-place 's/mark/mk/g' file # 替换所有行上的所有mark, 并保存到原文件
匹配 if (preg_match('/1999/', $s)) {
  echo "party!\n";
}
if (s.match(/1999/)) {
  console.log("party!");
}
"<i>markli".search(/>M/i) //2 ,如果没有匹配则返回-1

/\sli/g.exec("mark li") // [" li", index: 4, input: "mark li"], 不匹配则返回null
全局匹配,⚠️ 如果非//g 的正则会死循环
reg=/http[^\s]+/g
while (res = reg.exec(data)) { console.log(res[0]) } // 全局匹配,直到res 为 null

"2 3 4   5".split(/\s+/); // ["2", "3", "4", "5"]
import re
len(re.findall(r'1999',s2))>0
[[ "$1" =~ ^[0-9]{0,2}$ ]] && echo "yes"
捕获 $regex = '/^type=(9)&code=([0-9]{6})$/';
$matches = array();
if(preg_match($regex, $str, $matches)){
  echo 'type='.$matches[1];
  echo 'code='.$matches[2];
/page=([0-9]+)/.exec('&page=52&')[1] // 52

if(/page=([0-9]+)/.test('&page=52&')){alert(RegExp.$1*1+1);} // 53
match = re.compile(r'\d+').search('123mark456')
print(match.)
print(match.group())
动态构造正则 new RegExp(str+'$')
Array/Set
定义/申明 int arr[] = { 1, 2, 3, 4 };

int arr2[4];
arr2[1] = 1;

int matrix[2][3] = { {1, 4, 2}, {3, 6, 8} };
$arr = array(1, 2, 3, 4); var arr=[1, 2, 3, 4];
arr = new Array(10).fill().map((itm, idx) => idx)
arr = Array.from({ length: 10 }).map((itm, idx) => idx)

var set1=new Set()
var set2=new Set([1,2,3])
WeakSet 的成员只能是对象且不能forEach,并且和WeakMap一样是弱引用,如果存储的对象被GC, 它在WeakSet 里自动释放
前端常见内存泄漏及解决方法

TypedArray比Array省内存,长度是固定的,开了空间就不能改,他的值他存的是实际数据而不是指针
Int8Array 存-128~127范围的数字,超出范围取模后余数
Uint8ClampedArrayUint8Array 都是用来存0~255的数字,Unit8Array超出范围取模余数, 对于260和-10转化为4和246,Clamped对于260和-1转化为255和0,适合图像颜色计算
Uint16Array存0~65535范围
ArrayBuffer TypedArray 和 DataView
l=[1, 4] # list
t=('东','西','南','北') # tuple 不可修改元素值,元素个数
s=set(['python','java'])# set 无序不重复
arr=[arr1,arr2] 或 arr=[[1,2,3],['x','y']] # nest
arr=(1 2 3 4 5)
📐length/size printf("%lu", sizeof(arr)); // 数组内存字节长度
获得数组元素个数没有内置方法,可通过遍历计数获得
count($arr)
count($d)
arr.length
set1.size
len(squares)
len(tel)
echo ${#arr[*]}
Get value by index arr[0] $arr[0] arr[0]
arr.at(-1)
Array.from(set1)[0] // 先转化成数组
squares[0]
arr[1][1]
echo ${arr[0]}
Set value by index arr[0] = 8; $arr[0] = "lorem"; arr[0]="lorem";
set1.add(1)
squares[0]="lorem"
squares[2:4]=[99,100]
arr[0]="hi"
Fill 填充 ['vscode', 'notepad++', 'xmind', 'postman'].fill('terminal')
value是否存在于array

index of array element

count在array中出现的次数
if(in_array(2, $a)){}

$i = array_search("y", $arr);
['mark','emy'].indexOf('mark')>=0;
['mark','emy'].includes('mark') // ES5+
set1.has(3)
'm' in ['a', 'b', 'c'] # True/False

try:
    idx = ["x","y","z"].index("y")
    print("y第1次出现的位置", idx)
except ValueError:
    print("not in list")

['m', 'li', 'm'].count('m') > 0: # 返回2 统计出现的次数
数组slice切片
选择第3,4个元素
┏━┳━┓✂┏━┳━┓✂┏━┓ ┗━┻━┛ ┗━┻━┛ ┗━┛
array_slice($arr, 2, 2) arr.slice(2,4) // 切取 arr[2] ~ arr[4-1]
arr.slice(-2,-1) // 获得倒数第2个
squares[2:4]
slice to end 数组切到底
选择从第2个到尾部
┏━┓✂┏━┳━┳━┳━┓ ┗━┛ ┗━┻━┻━┻━┛
array_slice($arr, 1) arr.slice(1) squares[1:]
数组首部操作,追加与删除元素
┏━┓+┏━┳━┳━┳━┓ ┗━┛-┗━┻━┻━┻━┛
? var arr = [6, 7, 8]
arr.unshift(5)
arr.shift()
?
数组尾部操作,追加与删除元素 ┏━┳━┳━┳━┓+┏━┓ ┗━┻━┻━┻━┛-┗━┛ $arr = array(6, 7, 8);
array_push($arr, 9);
$arr[] = 9; # 与array_push相同
array_pop($arr);删除尾部元素
var arr = [6, 7, 8]
arr.push(9)
arr.pop() 或 arr.length--
list1.append(9)
list1.pop()
Insert an item into an array at a specific index arr.splice(_index, 0, item)
删除元素by index unset($arr[_index]);//数组将不会重建索引,若要重建索引用array_values($arr) arr.splice(_index,1)//前面一个参数数是删除的index,后面一参数表示删除后面的几个元素
delete arr[_index];//仍会占据一个长度,值为undefined
del a[0]
squares[2:4]=[]#删除2个
squares[:]=[]全部删除或squares.clear()
删除元素by value arr.splice(arr.indexOf('v'), 1)
合并
┏━┳━┳━┳━┓+┏━┳━┳━┳━┓ ┗━┻━┻━┻━┛+┗━┻━┻━┻━┛
$arr = array(1, 2, 3);
$arr2 = array(1, 2, 3);
print_r(array_merge($arr,$arr2));
var arr = [1,2,3],
arr2=[4,5,6];
console.log(arr.concat(arr2));
... 扩展(Spread)运算符
console.log([...arr,...arr2])
squares+[2,4,'mark']
扩展数组list1.extend(list2)
mergedTel=dict(tel,**tel2)
数组遍历
   ↆ ┏━┳━┳━┳━┳━┓ ┗━┻━┻━┻━┻━┛
int arr[4] = {1, 2, 3, 4};
for (int i = 0; i < 4; i++) {
  printf("%d\n", arr[i]);
}
foreach ($arr as $s) {
  echo "$s\n";
}
foreach($arr as $i => $s) {
  echo "$s at index $i";
}
⚠️ for in 中的index 不是数字,是字符串,而forEach中的index 是数字
for(idx in ['v']) { console.log(8+idx) } // 输出80
arr.forEach((item, index) => {})
forEach 无法用break 跳出可以用every 或some或find
every是遇到false就终止并返回false,some是遇到true就终止并返回true,find/findIndex是遇到true就终止并返回那个满足条件的item/index
arr.every((item, index) => {
  if (条件) {
    return false /* 相当于break */
  }
  return true
})
arr.some((item, index) => { // 或arr.find(
  if (条件) {
    return true /* 相当于break */
  }
  return false
})
for (let item of arr) {
for v in squares:
将范围转成数组 $a = range(1, 10); - l.list(range(1,10))
Reverse
┏━━━┳━━━┳━━━┳━━━┓ ┃ M ┃ a ┃ r ┃ k ┃ 🔁 ┗━━━┻━━━┻━━━┻━━━┛ ┏━━━┳━━━┳━━━┳━━━┓ ↵ ┃ k ┃ r ┃ a ┃ M ┃ ┗━━━┻━━━┻━━━┻━━━┛
$a = array(1, 2, 3);
$a = array_reverse($a);
print_r($a);
var a = [1, 2, 3];
a.reverse();
console.log(a);
a.reverse().join(' ')===a.join(' ') 一定为真,reverse 操作数组本身
l=[1,2,3]
l.reverse()
print(l)
Sort
default by ASCII code
┏━━━┳━━━┳━━━┳━━━┓ ┃ M ┃ a ┃ r ┃ k ┃ 📶 ┗━━━┻━━━┻━━━┻━━━┛ ┏━━━┳━━━┳━━━┳━━━┓ ↵ ┃ M ┃ a ┃ k ┃ r ┃ ┗━━━┻━━━┻━━━┻━━━┛
$a = array("b","A","a","B");
sort($a);
print_r($a);
[15,6,5].sort() // [15, 5, 6] 按字符串排序, 15会排在5前,因为起始字符是1
[15,5,6].sort((a,b)=>a-b) // 数字排序

sort 回调返回的必须是数字,不是true 或 false,否则出错
['ab','aa','bb'].sort((a,b) => a<b) // ❌['ab','aa','bb']
['ab','aa','bb'].sort((a,b) => a<b?-1:1) // ['aa','ab','bb']

字符个数相同,则按照ASCII码由小到大排序输出
Object.keys(obj).sort((a,b) => {
  if (obj[a] === obj[b]) {
    return a.charCodeAt() - b.charCodeAt()
  } else {
    return obj[b] - obj[a]
  }
})
Array.from(set).sort() // Set 没有数组方法
a=["b","A","a","B"]
a.sort()
重复数据删除(去重)
┏━━━┳━━━┳━━━┳━━━┓ ┃ M ┃ o ┃ o ┃ n ┃ ┗━━━┻━━━┻━━━┻━━━┛ ┏━━━┳━━━┳━━━┓ ↵ ┃ M ┃ o ┃ n ┃ ┗━━━┻━━━┻━━━┛
$a = array(1, 2, 2, 3);
$a=array_unique($a);
arr = [1,2,3,3]
Array.from(new Set(arr)) 或者[...new Set(arr)]
-
洗牌和取样 ⚀⚁⚂⚃⚄⚅ $a = array(1, 2, 3, 4);
shuffle($a);//洗牌
$sa=array_rand($a, 2);//随机截取
- -
过滤
┏━━━┳━━━┳━━━┳━━━┓ ┃ ( ┃ { ┃ [ ┃ ? ┃ ┗━━━┻━━━┻━━━┻━━━┛ ┏━━━┳━━━┳━━━┓ ↵ ┃ ( ┃ { ┃ [ ┃ ┗━━━┻━━━┻━━━┛
arr.filter(item=>item>10)

设置过滤后长度为0时的默认值
filter(condition).concat({ field: 'default' })[0].field
按条件查找 [88, 93, 95].find(item=>item>90) // 93
[88, 93, 95].findIndex(item=>item>90) // 1
Reducer arr.reduce((total, item)=>total+item) // 累加
Map collections.map((item)=> item.title)
// ['title1', 'title2', 'title3']

// 获得数组中数字为奇数项的index
[1,2,3,4,5]
  .map((itm, idx) => itm % 2 ? idx : -1)
  .filter(item => item !== -1)
扁平化Flat [1,2,[3,4],[[5,6]],[[[7,8]]],[[[[9,10]]]]].flat(2) // [1, 2, 3, 4, 5, 6, Array(2), Array(1)]
[1,2,[3,4],[[5,6]],[[[7,8]]],[[[[9,10]]]]].flat(Infinity) // [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

['May the force', 'be with you'].flatMap(item=>item.split(' ')) // ['May', 'the', 'force', 'be', 'with', 'you']
Object/Map/Dict/struct
定义/申明 struct myStructure {
  int myNum;
  char myLetter;
  char myString[30];
};

struct myStructure s1;
s1.myNum = 13;
s1.myLetter = 'B';
// s1.myString = "hi"; // Error
strcpy(s1.myString, "hi")

struct myStructure s2 = {13, 'B', "mark"}; // 更简单的语法

struct myStructure s3;
s3 = s1; // 深拷贝
$d = array("t" => 1, "key" => 0); var obj={t:1,key:0}

const map1=new Map();
b={a:1}
map1.set(b, 'v')
map1.get(b)
const map2=new Map([["k1","v1"],["k2","v2"]]);
map2.get("k1") // v1
WeakMap的key 必须为引用值,当这个key不被引用,会被GC 回收,从而从WeakMap 里自动释放, WeakMap且不能被forEach。Map 的 key 啥类型都行,但影响GC 回收该key 导致内存泄漏,Map支持forEach
wmap = new WeakMap()
前端常见内存泄漏及解决方法
d = {"state": 4, "action": "VO"} # dict declare -A tel
tel=([Mark]=6015 [Emy]=0755)
📐length/size map1.size
Get value by key🔑 s1.myNum $d["t"] _obj.t 或 _obj["t"] d['jack'] echo ${tel[Mark]}
Set value by key🔑 s1.myNum = 14;
strcpy(s1.myString, "Something else");
? map2.set("k3","v3");
theHobbit.stars = 4 // stars set to 4
d['jack'] = 5
Ferrari458.brand
tel[Mark]=6016
key🔑是否存在 if(array_key_exists("key", $d)) 'key' in obj
map1.has('key')
if 'jack' in tel:#还可以使用not in
删除元素by key🔑 unset($d["t"]); delete _obj.t; del tel['sape']
合并覆盖Object ? Object.assign(default_opt, opt)
... 扩展(Spread)运算符
option = { ...default_opt, ...opt}
对象遍历 foreach ($d as $k => $v) {echo $k.'=>'.$v;} for(let key in arr_obj){
  console.log(arr_obj[key]);
}
for v in d:
Get all keys🔑🔑 & Get all values 转成数组 array_keys($d)
array_values($d)
Object.keys(obj) // Output ['t', 'key']
Object.values(obj) // Output [1, 0]
Object.entries(obj) // Output [['t', 1], ['key', 0]]

注意对象输出是按插入顺序而不是名称排序
obj = {}
obj.B = 1,obj.A = 2
Object.keys(obj)[0] === 'B' // true
list(tel.keys())
list(tel.values())
Function
定义函数 void myFunction(char name[]) {
  printf("Hello %s\n", name);
}

int main() {
  myFunction("World");
  return 0;
}

不能在申明前调用函数, 函数可以先申明后定义
void myFunction (char []);
void main() {}
void myFunction(char name[]) {
function add3($x1, $x2, $x3)
{
  return $x1 + $x2 + $x3;
}
function add3(x1, x2, x3)
{
   return x1 + x2 + x3;
}
function add3([x1,x2,x3]) { return x1+x2+x3;}
function myfun({x,y,z}) { return x*y-z;}
def add3(x1,x2,x3):
    return x1+x2+x3
function add3(){
echo $[$1+$2+$3]
}
Arrow Function
有点像pipeline,箭头前的输出是箭头后的输入
- - 箭头函数可省去return
(param1, param2, …, paramN) => { statements }
(param1, param2, …, paramN) => expression
// 等价于: => { return expression; }
只返回{}, 应当用()将其包起来, 否则当statements处理而不是当expression处理
params => ({foo: bar})
如果只有一个参数,可以不加圆括号:
singleParam => { statements }
无参数的箭头函数需要使用圆括号或者下划线
() => { statements }
或 _ => { statements }
箭头函数的this始终继承父级作用域的,且不能作为构造函数
- -
调用函数 ? add3(1, 2, 3); add3(1, 2, 3)
add3([1,2,3]);
myfun({x:3,z:2,y:1});// output: 1
add3(1, 2, 3)add3 2 3 8 #打印结果13
数组作参数 ? $arr = array(1, 2, 3);
function foo($ar){}
echo foo($arr);
... 扩展(Spread)运算符
arr = [1,2,3]
foo = (x,y,z)=> x*y*z
console.log(foo(...arr))

Math.max(...arr)
l=[1,2,3]
def foo(arr):
    for v in arr:
        print(v)

foo(l)
rest参数 ? - function add(...values) {
for let v of values){
...
add(2,5,7)
函数作参数 ? function add($x,$y,$f){
  return $f($x)+$f($y);
}
function add(x,y,f){
  return f(x)+f(y)
}
def add(x, y, f):
  return f(x) + f(y)
默认参数 ? function my_log($x, $base=10)
{
  return log($x) / log($base);
}

my_log(42);
my_log(42, M_E);
function my_log(x, base)
{
  base = arguments[1] ? arguments[1]:10;
  return Math.log(x) / Math.log(base);
}

my_log(42);
my_log(42, Math.E);

function my_log(x, base=10)
import math
def my_log(x, base=10):
    return math.log(x) / math.log(base)

my_log(42);
my_log(42, math.e)
可变数目的参数 ? function first_and_last()
{
  $arg_cnt = func_num_args();

  if ($arg_cnt >= 1) {
    $first = func_get_arg(0);
    echo "first: " . $first . "\n";
   }

   if ($arg_cnt >= 2) {
     $arr = func_get_args();
     $last = $arr[$arg_cnt-1];
     echo "last: " . $last . "\n";
   }
}
function howManyArgs(){
  console.log(arguments.length);
  console.log("Hello"+arguments[0]+","+arguments[1]);
}
howManyArgs("string", 45);
Python可变参数
传地址参数 ? function foo (&$x, &$y)
{
  $x += 1;
  $y .= "ly";
}

$n = 7;
$s = "hard";
foo ($n, $s);
- -
匿名(Anonymous)函数 ? $sqr = function ($x) {
   return $x * $x;
};
echo $sqr(3);
IIFE(Immediately-Invoked Function Expression)立即调用函数表达式
自调用函数(self-invoking function)
有两种写法,没实际区别
(function () {})()
(function () {}())
lambda用于创建匿名函数
回调模式
Callback
? call_user_func('myfun')
call_user_func('myfun','myparam')
function call_func(function_param) {
   function_param();
}
function myfunc() {
   // ...
}
call_func(myfunc);
例:requestAnimationFrame
def callback(fun):
  fun()
def myfun():
   print('hi,mark')
callback(myfun)
sync and async //异步1: Callback
getData(a => {
  getMoreData(a, b => {
    getMoreData(b, c => {
    })
  })
})
//异步2: Promise
function getData() {
  return new Promise((resolve, reject) => {
    fs.readFile(fileName, (error, data) => {
      if (error) { reject(error) }
      else { resolve(data) }
    })
  })
}
getData()
  .then(a => getMoreData(a))
  .then(b => getMoreData(b))
  .then(c => {})
  .catch(err => {})
//异步3: async/await, async 是Generator 的语法糖
const foo = async function() {
  try {
    let a = await this.apis.getData()
    let b = await this.apis.getMoreData(a)
  } catch(err) {}
}
定义类 - class Book{
  private $isbn;
  public $title;
  public $author;
  public function __construct($isbn, $title = null, $author = null) { // 构造函数
    $this->isbn = $isbn;
    $this->title = $title;
    $this->author = $author;
  }
  public function display() {
    echo $this->isbn;
  }
}
var Book = /** @class */ function(isbn, title, author) {
  if(isbn == undefined) throw new Error('Book constructor requires an isbn.');
  this.isbn = isbn;
  this.title = title || 'No title specified';
  this.author = author || 'No author specified';
}

Book.prototype.display = function() {
  ...
};
//或者
Book.prototype = {
  checkIsbn: function(isbn) {
    ...
  },
  display: function() {
    ...
  }
};

ES6 的类是基于原型语法的语法糖
class Book {
  constructor(isbn, title, author) {
    if(isbn == undefined) throw new Error('Book constructor requires an isbn.');
    this.isbn = isbn;
    this.title = title || 'No title specified';
    this.author = author || 'No author specified';
  }
  display () {
    console.log(this.isbn)
  }
  get stars () {
    return 5
  }
  set stars (newval) {
    console.log('stars set to ', newval)
  }
}
class Car:
  def __init__(self,brandname,horsepower):
    self.brand = brandname
    self.power = horsepower
  def drive(self):
    print('Run with %s horsepower' % self.power)

也可以这样玩
class Car:
  pass
LamborghiniAventador = Car()
LamborghiniAventador.brand = 'Lamborghini'
LamborghiniAventador.power = 700
Using a Class to Instantiate an Object $theHobbit = new Book('isbn', 'The Hobbit', 'mark') var theHobbit = new Book('isbn', 'The Hobbit', 'mark') ?
method $theHobbit->display(); theHobbit.display(); Ferrari458.drive()
value $theHobbit->isbn; // Cannot access private property Book::$isbn

$obj->$param; // 动态
$obj->{$param . 's'}
theHobbit.isbn Ferrari458.brand
访问修饰符
实现封装,减少耦合
public:全开
protect:仅同一个类或子类能访问
private:仅同一个类能访问
class默认访问修饰符为 public
js self.__privateattr
要让内部属性不被外部访问,可把属性名称前加__
但某些版本的解析器中你依然可以用obj._classname__privateattr来访问,也就是Python本身没有任何机制阻止你干坏事,一切靠自觉养成好习惯
继承 class ITBook extends Book {
  public $technology;
  public function __construct($isbn, $title, $author, $technology) {
    parent::__construct($isbn, $title, $author);
    $this->technology = $technology;
  }
}
A对象应用B对象的方法
B.apply(A, arguments);
B.call(A, args1,args2);

class ITBook extends Book {
  constructor(isbn, title, author, technology) {
    super(isbn, title, author);
    this.technology = technology;
  }
}
class Dog(Animal):狗继承动物类,获得动物类的全部功能财产
重载(Overloading) & 重写(Overriding) php - 子类的run()覆盖了父类的run(),在代码运行的时候,总是会调用子类的run()
静态语言需要重载解决调用灵活性,而Python这种灵活的语言可以用其它方式实现
多态
同一个接口,使用不同的实例而执行不同操作
实现多态的必要条件继承+重写+父类引用指向子类对象
php js ?
Control Flow
if if(条件1){
  执行1
} else if(条件2){
  执行2
} else{
  执行3
}
第一种方式同java
第二种方式将else if替换成elseif, 据说这个更有效率
第三种方式用:代替大括号,不能用else if

if(条件1):
  执行1
elseif(条件2):
  执行2
else
  执行3
endif;
if(条件1){
  执行1
} else if(条件2){
  执行2
} else{
  执行3
}
if 条件:
elif 条件2:
else:
if [ $1 -gt 30 ];then
echo 'Not kid any more'
elif [ $1 -gt 20 ];then
echo 'Become mature'
else
echo 'you are young'
fi
注意[ ]两边都得要有空格
if [ ! -n "$1" ]; then # 变量是否存在
if [ ! -d "web-cms" ]; then # 目录是否存在
if [ ! -f "spm.zip" ]; then # 文件是否存在
if [[ "" =~ ^[0-9]{0,2}$ ]]; then # 正则条件双括号[[ ]]
三元运算符 x=(x > 0 ? x :-x); $x > 0 ? $x : -$x x=(x > 0 ? x :-x) - -
switch
switch (n) {
case 0:
   printf("no hits\n");
   break;
case 1:
   printf("one hit\n");
   break;
default:
   printf("%d hits\n", n);
}
switch (n) {
case 0:
   echo "no hits";
   break;
case 1:
   echo "one hit";
   break;
default:
   echo n." hits";
}
switch (n) {
case 0:
   console.log("no hits");
   break;
case 1:
   console.log("one hit");
   break;
default:
   console.log(n+" hits");
}
为什么Python没有switch?
少量用if elif
大量用字典
func = functions[value]
func()
case $1 in
男|M)
echo "小少爷"
;;
女|F)
echo "小公主"
;;
*)
echo "有没有搞错"
;;
esac
while 🔁 1┏━▶⚙━━┓ ━━▶while◀━━┛ 0┗━━━━━▶ a period of time. while ( i < 100 ) {
  i++;
}
while ( i < 100 ) {
  i++;
}
while ( i < 100 ) {
  i++;
}
while i < 100 :
    i+=1;
while [ $i -lt 10 ]; do
let i=i+1
done

while true; do
# 无限循环用Exit跳出
do while 🔁 ━━▶⚙◀━━━┓1 0 ┗━━while━━▶ 和while循环十分类似,
不过至少执行一次代码
do{
  sum=sum+i;
  i++;
}while(i<=100);
do{
  sum=sum+i;
  i++;
}while(i<=100);
do{
  sum=sum+i;
  i++;
}while(i<=100);
无,用break跳出
for循环 🔁 for(int i=1;i<=5;i++) {
   sum=sum+i;
}
for(i=1;i<=5;i++) {
   sum=sum+i;
}
for(i=1;i<=5;i++) {
   sum=sum+i;
}
for i in range(1,6): # range为遍历辅助
  sum+=i
for i in `seq 1 3`;do echo $i;done
for i in 1 2 3;do echo $i;done
break, continue
跳出最近一层的for,for-in,while,do-while循环, 或跳出switch
continue只结束本次循环,直接进入下一轮
break则是结束整个循环

✍ 遇到难题停止继续做下一题: continue,撕卷子: break
break, continue break, continue break, continue break, continue break, continue
goto - if(1) goto end;
...
end:
...
不能跨函数使用.This is not a full unrestricted goto,The target label must be within the same file and context
- - -
exit exit(); // 别名die, 输出一个消息并且退出当前脚本 - os._exit() # 终止程序
sys.exit() # 会引发一个异常,如果异常没被捕获,python解析器将会退出,如果被捕获,还可以执行后面的代码,用于做清理工作

一般情况下使用sys.exit()即可,一般在fork出来的子进程中使用os._exit()
exit
Sleep 🚦⏱ sleep(5) const sleep = sec => new Promise(resolve => setTimeout(resolve, sec * 1000));
await sleep(5)
import time
time.sleep(5)
sleep 5
异常的抛出与捕获
无论异常是否发生,在程序结束前,finally中的语句都会被执行
//主动抛出异常
function checkNum($number){
  if($number>1){
        throw new Exception("不能使用大于1的值");
  }
  return true;
}

try {
   checkNum(2);
} catch (Exception $e){
   echo '错误描述: ' .$e->getMessage();
} finally {
  echo "always excute";
}
//被动抛出异常
try {
  adddlert("Welcome!");
}  catch (err){
  alert(err);//ReferenceError: adddlert is not defined
}

//主动抛出异常
try {
  throw "抛出错误"
}  catch (err){
  alert(err);//抛出错误
}
finally {console.log("always excute")}
# 被动抛出
import sys
try:
  f = open('myfile.txt')
  s = f.readline()
  i = int(s.strip())
except OSError as err:
  print("OS error: {0}".format(err))
except ValueError:
  print("Could not convert data to an integer.")
except:
  print("Unexpected error:", sys.exc_info()[0])
finally:
  print("always excute")

# 主动抛出
try:
  raise ValueError
except:
  print("value error")
npm run build || (echo '编译失败';exit 1)

npm run build
if [ $? -ne 0 ];then
echo '编译失败'
exit 1
else
echo '编译成功'
fi
CLI
命令行 gcc main.c // 编译
./a.out // 运行
objdump -D a.out 查看指令
php -f index.php
php -r "echo 'mark';"
node bgt.js file

TypeScript
tsc main.ts // 编译成main.js
python3 cmd.py ip 116.6.65.67 Method 1:
bash backupdb.sh arg1 arg2
Method 2:
./backupdb.sh # need shebang and X permission
REPL
Read-Eval-Print Loop
Interactive shell
- php -a
> 1+2
> exit
node
> 1+2
>.exit
python3
>>> 1+2
>>> exit()
-
参数 int main (int argc, char *argv[]) { // (参数个数,参数数组)
  printf("共有%d个参数\n", argc);
  printf("第一个参数是%s\n", argv[0]); // 第一个参数是./a.out
  return 0;
}
$argv 数组
$argv[0]是脚本名
$argv[1]是第一个参数
Node.js
const args = process.argv.slice(2)
process.argv[0] 是node程序地址,process.argv[1] 是脚本名
import sys#需要模块:sys
sys.argv[0]#脚本名:cmd.py
sys.argv[1]#参数1:ip
脚本中$1的值便是arg1, $2便是arg2, $@值是所有参数arg1 arg2
输入 char input[10];
int num;
printf("指令>>");
scanf("%9s", input); // 最大长度9个字符,否则溢出
printf("%s\n", input);
printf("数字>>");
scanf("%d", &num); // 这里需要是指针,而上面的input数组本身是指针
printf("%d\n", num);
fwrite(STDOUT, "M>>");
echo fgets(STDIN);
const readline = require('readline').createInterface({
  input: process.stdin,
  output: process.stdout
});
readline.question('M>> ', taskid => {
  console.log(taskid)
  // readline.close();
});
command = input("M>>")
print(command)
read -p "M>> " taskid
echo $taskid
调用命令行 import os
os.system('start https://x.com')
-
Disk I/O
判断目录/文件是否存在 if (file_exists('dirNameOrFileName')) {
  echo "文件或目录存在";
}
const fs = require('fs')
if (fs.existsSync('/path/dir')){
if (fs.existsSync('/path/file.txt')){
import os
if not os.path.exists(aim_dir+'\\'+name):
# 如果文件/目录不存在

os.path.isdir(ori_dir+'\\'+name):
# 是否是目录
os.path.isfile(ori_dir+'\\'+name):
# 是否是文件
if [ ! -d "web-cms" ]; then # 目录是否存在
if [ ! -f "spm.zip" ]; then # 文件是否存在
Create/Remove directory/file, write/read file FILE *fptr;
fptr = fopen("filename.txt", "w");
fprintf(fptr, "Some text\n");
fclose(fptr);

fptr = fopen("filename.txt", "r");
char myString[100];
while(fgets(myString, 100, fptr)) {
  printf("%s", myString);
}
mkdir("/path/to/my/dir", 0700);

$f = fopen("f.txt", "w");
fwrite($f, 'content');
fclose($f);
带Sync的函数都是同步方法,没有回调
fs.mkdirSync('/path/newdir')
fs.rmdir('/path/dir',()=>{console.log('callback')})

fs.writeFileSync('/path/newfile.txt', 'Hello\n') // 不存在则新建文件
fs.appendFileSync('/path/newfile.txt', 'line2\n') // 追加加入
fs.unlinkSync('/path/file.txt')// 删除文件

fs.readFile('/path/file.txt', (err,data) => { console.log(data.toString()) })
import os
os.makedirs(aim_dir)

f=open('f.txt','w')
f.write('content')
f.writelines(['content\n','content2\n'])
f.close()
mkdir www
touch file
echo 'content' >> file
获得文件扩展名 const path = require('path');
console.log(path.extname('/path/file.txt')) // .txt
import os
os.path.splitext('a.b.txt') # ('a.b', '.txt')
file=a.b.txt
echo "${file%.*}" # a.b
echo "${file##*.}" # txt
遍历文件 带Sync的函数都是同步方法,没有回调
const fs = require('fs');
const path = require('path');
function traverseDir(dir) {
  const files = fs.readdirSync(dir); // 读取目录
  for (let file of files) {
    const filepath = path.join(dir, file);
    const stats = fs.statSync(filepath); // 获取文件信息
    if (stats.isDirectory()) {
        traverseDir(filepath);
    } else {
        console.log(filepath);
    }
  }
}

traverseDir('/path/dir')
import os
for dirpath, dirnames, filenames in os.walk(path):
    print(dirpath)
    print(filenames)
-
netWork I/O
HTTP Data ? $_POST $_GET $_COOKIE
$_REQUEST(包含$_POST+$_GET+$_COOKIE 数据的数组)
$_SERVER['HTTP_IF_NONE_MATCH']
'https://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI'] 判断协议,别忘记考虑负载均衡
window.location, document.cookie

const urlParams = new URLSearchParams(location.hash.replace(/^.*\?/, ''))
urlParams.get('param')
? -
HTTP Server ? header()
setcookie()
Node.js
python3 -m http.server [port] // 适合HTML页面

Simple Server Demo
HTTP Client ? cURL jquery.ajax
Fetch fetch(url).then(res => { return res.json() }).then(myjson => {}).catch(err=>{})
- curl
wget
Time
Get Time #include <time.h>

time_t current_time;
time(&current_time);
printf("%ld\n", (long)current_time); // 1684367117

time_t current_time;
time(&current_time);
struct tm* time_info;
char time_string[20];
time_info = localtime(&current_time);
strftime(time_string, sizeof(time_string), "%Y-%m-%d %H:%M:%S", time_info);
printf("%s\n", time_string); // 2023-05-18 15:38:43
echo date("Y-m-d H:i:s");
//Output: 2018-05-03 01:06:54
//Other format
date(m);
date(H);
echo time();
//Output: 1525309469
var d=new Date();
console.log(d.toLocaleString())
//Output: 5/2/2018, 2:18:36 PM

Date.parse(new Date())/1000
//Output: 1525242393
parseInt(new Date().getTime()/1000)
//Output: 1525242680

parseInt((new Date()).valueOf()/1000)
//Output 1525243045
import time;
print(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
#Output: 2018-05-03 10:17:01

print(int(time.time()))
#Output: 1525310230
echo `date`
#Output: Wed May 2 13:54:46 2018
echo "[`date +%Y-%m-%d\|%T\|%A`]"
#Output: [2018-05-02|14:14:20|Wednesday]
echo `date +%s`
#Output: 1525242150
Datetime to Timestamp char datetime_str[] = "2023-05-18 10:38:43";
struct tm datetime;
time_t timestamp;
strptime(datetime_str, "%Y-%m-%d %H:%M:%S", &datetime);
timestamp = mktime(&datetime);
printf("%ld\n", (long)timestamp); // 1684373923
echo strtotime("2018-10-06 02:00:00");
//Output: 1538791200
Date.parse(new Date("2018-10-06 02:00:00"))/1000 import datetime
import time

print(time.mktime(datetime.datetime.strptime("2021-05-12 02:37:29", "%Y-%m-%d %H:%M:%S").timetuple()))
// output: 1620758249.0
-
Timestamp to Datetime time_t timestamp = 1684373923;
struct tm* datetime = localtime(×tamp);
char datetime_str[20];
strftime(datetime_str, sizeof(datetime_str), "%Y-%m-%d %H:%M:%S", datetime); // 2023-05-18 09:38:43
printf("%s\n", datetime_str);
echo date("Y-m-d H:i:s",'1538791200000'/1000);
// output:2018-10-06 02:00:00
function formatDate(_timestamp) {
  let date = new Date(+_timestamp),
  year = date.getFullYear(),
  month = String(date.getMonth() + 1).padStart(2, '0'),
  day = String(date.getDate()).padStart(2, '0'),
  hour = String(date.getHours()).padStart(2, '0'),
  min = String(date.getMinutes()).padStart(2, '0'),
  sec = String(date.getSeconds()).padStart(2, '0');
  return `${year}-${month}-${day} ${hour}:${min}:${sec}`
}

formatDate(1538791200*1000)
from datetime import datetime

print(datetime.fromtimestamp(1620758249))
// output: 2021-05-12 02:37:29
-
其他 new Date(new Date(2023,2,0).getTime() + (24 * 3600 - 1) * 1000)
// Tue Feb 28 2023 23:59:59 ... 获得月底最后一天的最后一秒
Encryption
base64 ? echo base64_encode("mark李"); // bWFya+adjg==
echo base64_decode("bWFya+adjg=="); // mark李
window.btoa(unescape(encodeURIComponent("mark李"))); //'bWFya+adjg=='
decodeURIComponent(escape(window.atob('bWFya+adjg=='))); // 'mark李'
import base64
print(base64.b64encode("mark李".encode("utf-8")).decode("utf-8")) // bWFya+adjg==
print(base64.b64decode("bWFya+adjg==").decode("utf-8")) // mark李
echo -n mark李|base64 // bWFya+adjg== 加-n 来确保字符串不包含行末换行符
echo bWFya+adjg==|base64 -d // mark李%
echo mark李|base64 // bWFya+adjgo=
echo bWFya+adjgo=|base64 -d // mark李
Hash: md5, sha1, sha256, sha512 ? echo md5("mark李"); // 8ef85f394180bc4a79a47b033440d7fd md5 calculate(.trans.)
md5("mark李"); // 8ef85f394180bc4a79a47b033440d7fd
import hashlib

print(hashlib.md5(bytes('mark李',encoding='utf-8')).hexdigest()) // 8ef85f394180bc4a79a47b033440d7fd

import os
hashlib.sha1(open('C:\\Users\\m\\Desktop\\file.exe','rb').read()).hexdigest()
hashlib.sha256(...
hashlib.sha512(...
echo -n mark李|md5sum # 8ef85f394180bc4a79a47b033440d7fd -
echo -n mark李|openssl md5 # 8ef85f394180bc4a79a47b033440d7fd

cat file|md5sum
cat file|openssl sha1
cat file|openssl sha256
cat file|openssl sha512
对称加密: aes $iv='';
$str = openssl_decrypt(hex2bin($key), "aes-128-ecb", $aeskey, OPENSSL_RAW_DATA, $iv);

openssl_encrypt
? ? ?
非对称加密: RSA ? ? ? ? ssh-keygen -t rsa -f ~/.ssh/markli_rsa -N ""
read -p "输入目标IP>> " ip
scp ~/.ssh/markli_rsa.pub root@$ip:~/markli_rsa.pub
ssh root@$ip "cat ~/markli_rsa.pub >> ~/.ssh/authorized_keys"
ssh root@$ip "rm ~/markli_rsa.pub"
  • Basic
  • Value & Type
  • Number & Operators
  • String
  • RegEx
  • Array
  • Object
  • Function & Class
  • Control Flow
  • CLI
  • Disk I/O
  • netWork I/O
  • Time
  • Encryption
  • 一个程序包括两个方面的内容:Data structure(指定数据的类型和数据的组织形式) ; Algorithm(对数据操作的步骤)

    "不要觉得为用户着想就是让他们使用像英语一样又长又啰嗦的语法。如果你让黑客像下面这样求和:add x to y giving z 而不是写成: z=x+y 那么你就是在侮辱黑客的智商" - 《黑客与画家》

    "如果你开始认真地编程,你最终将不得不学习 C,Unix 的核心语言。实际上您越能避免使用 C 编程,您的工作效率就会越高。C 非常高效且非常节省机器资源。但C 通过手动对资源(如内存)进行大量低级管理来获得这种效率。所有这些低级代码都很复杂且容易出错,并且会占用您大量的调试时间。" - 《How To Become A Hacker》

    SINCE 2015 © markbuild