外汇EA——基于均线的简单EA

```//+------------------------------------------------------------------+
//|                                                        ma_ea.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property version   "1.00"
#property strict

#define MAGIC_NUM 20150312

//--- input parameters
input int      period=19;
input int      max_orders=10;
input double      per_lot=0.01;
input double   risk_rate=0.1;

double calcLots() {
double   lot=per_lot;
double minLot = MarketInfo(Symbol(),MODE_MINLOT);

lot=NormalizeDouble(risk_rate*AccountFreeMargin()/AccountLeverage(),1);

if(lot<0.1) lot=0.1;
if(lot<minLot) lot=minLot;
return(lot);
}

void CheckForOpen()
{
double ema;
double sma;
int    res;
//--- go trading only for first tiks of new bar
//   if(Volume[0]>1) return;
//--- get Moving Average
sma=iMA(NULL,0,period,0,MODE_SMA,PRICE_CLOSE,0);
ema=iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,0);

//--- sell conditions
if(Open[1]>ema && Open[1]>sma && ema<sma && Close[1]<ema && Close[1]<sma)
{
res=OrderSend(Symbol(),OP_SELL,calcLots(),Bid,3,0,0,"",MAGIC_NUM,0,Red);
return;
}
if(Open[1]<ema && Open[1]<sma && Close[1]>sma && Close[1]>ema && ema>sma)
{
return;
}
//---
}
//+------------------------------------------------------------------+
//| Check for close order conditions                                 |
//+------------------------------------------------------------------+
void CheckForClose()
{
double sma;
double ema;
//--- go trading only for first tiks of new bar
//   if(Volume[0]>1) return;
//--- get Moving Average
sma=iMA(NULL,0,period,0,MODE_SMA,PRICE_CLOSE,0);
ema=iMA(NULL,0,period,0,MODE_EMA,PRICE_CLOSE,0);
//---
for(int i=0;i<OrdersTotal();i++)
{
if(OrderMagicNumber()!=MAGIC_NUM || OrderSymbol()!=Symbol()) continue;
//--- check order type
{
if(Open[1]>sma && Open[1]>ema && Close[1]<ema && Close[1]<sma && ema<sma)
{
if(!OrderClose(OrderTicket(),OrderLots(),Bid,3,White))
Print("OrderClose error ",GetLastError());
}
break;
}
if(OrderType()==OP_SELL)
{
if(Open[1]<sma && Open[1]<ema && Close[1]>ema && Close[1]>sma && ema>sma)
{
Print("OrderClose error ",GetLastError());
}
break;
}
}
//---
}

//+------------------------------------------------------------------+
//| Expert initialization function                                   |
//+------------------------------------------------------------------+
int OnInit()
{
//---

//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Expert deinitialization function                                 |
//+------------------------------------------------------------------+
void OnDeinit(const int reason)
{
//---

}
//+------------------------------------------------------------------+
//| Expert tick function                                             |
//+------------------------------------------------------------------+
void OnTick()
{
//---

if(OrdersTotal() <=10) CheckForOpen();                            //
else  CheckForClose();
}
//+------------------------------------------------------------------+
```

外汇指标——Moving Averages

2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55
2015.01.06 1218.15
2015.01.07 1210.64
2015.01.08 1208.42
2015.01.09 1222.65
2015.01.12 1227.33

2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55 1191.548
2015.01.06 1218.15 1198.584
2015.01.07 1210.64 1200.708
2015.01.08 1208.42 1205.96
2015.01.09 1222.65 1212.882
2015.01.12 1227.33 1217.438

2014.12.29 1182.97
2014.12.30 1200.02
2014.12.31 1182.16
2015.01.02 1188.04
2015.01.05 1204.55 1191.548 1193.626667
2015.01.06 1218.15 1198.584 1202.494
2015.01.07 1210.64 1200.708 1206.512667
2015.01.08 1208.42 1205.96 1209.083333
2015.01.09 1222.65 1212.882 1214.646667
2015.01.12 1227.33 1217.438 1219.462667

EMA的公式推导见

Include文件夹下看MovingAverages.mqh这个头文件

```//+------------------------------------------------------------------+
//|                                               MovingAverages.mqh |
//|                   Copyright 2009-2013, MetaQuotes Software Corp. |
//|                                              http://www.mql5.com |
//+------------------------------------------------------------------+
#property copyright "2009, MetaQuotes Software Corp."
//+------------------------------------------------------------------+
//| Simple Moving Average                                            |
//+------------------------------------------------------------------+
double SimpleMA(const int position,const int period,const double &price[])
{
//---
double result=0.0;
//--- check position
if(position>=period-1 && period>0)
{
//--- calculate value
for(int i=0;i<period;i++) result+=price[position-i];
result/=period;
}
//---
return(result);
}
//+------------------------------------------------------------------+
//| Exponential Moving Average                                       |
//+------------------------------------------------------------------+
double ExponentialMA(const int position,const int period,const double prev_value,const double &price[])
{
//---
double result=0.0;
//--- calculate value
if(period>0)
{
double pr=2.0/(period+1.0);
result=price[position]*pr+prev_value*(1-pr);
}
//---
return(result);
}
//+------------------------------------------------------------------+
//| Smoothed Moving Average                                          |
//+------------------------------------------------------------------+
double SmoothedMA(const int position,const int period,const double prev_value,const double &price[])
{
//---
double result=0.0;
//--- check position
if(period>0)
{
if(position==period-1)
{
for(int i=0;i<period;i++) result+=price[position-i];
result/=period;
}
if(position>=period)
result=(prev_value*(period-1)+price[position])/period;
}
//---
return(result);
}
//+------------------------------------------------------------------+
//| Linear Weighted Moving Average                                   |
//+------------------------------------------------------------------+
double LinearWeightedMA(const int position,const int period,const double &price[])
{
//---
double result=0.0,sum=0.0;
int    i,wsum=0;
//--- calculate value
if(position>=period-1 && period>0)
{
for(i=period;i>0;i--)
{
wsum+=i;
sum+=price[position-i+1]*(period-i+1);
}
result=sum/wsum;
}
//---
return(result);
}
//+------------------------------------------------------------------+
//| Simple moving average on price array                             |
//+------------------------------------------------------------------+
int SimpleMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& buffer[])
{
int i,limit;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
if(as_series_price)  ArraySetAsSeries(price,false);
if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
if(prev_calculated==0) // first calculation
{
limit=period+begin;
//--- set empty value for first bars
for(i=0;i<limit-1;i++) buffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
firstValue+=price[i];
firstValue/=period;
buffer[limit-1]=firstValue;
}
else limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total;i++)
buffer[i]=buffer[i-1]+(price[i]-price[i-period])/period;
//--- restore as_series flags
if(as_series_price)  ArraySetAsSeries(price,true);
if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//|  Exponential moving average on price array                       |
//+------------------------------------------------------------------+
int ExponentialMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& buffer[])
{
int    i,limit;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
double dSmoothFactor=2.0/(1.0+period);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
if(as_series_price)  ArraySetAsSeries(price,false);
if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
limit=period+begin;
//--- set empty value for first bars
for(i=0;i<begin;i++) buffer[i]=0.0;
//--- calculate first visible value
buffer[begin]=price[begin];
for(i=begin+1;i<limit;i++)
buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);
}
else limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total;i++)
buffer[i]=price[i]*dSmoothFactor+buffer[i-1]*(1.0-dSmoothFactor);
//--- restore as_series flags
if(as_series_price)  ArraySetAsSeries(price,true);
if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//|  Linear weighted moving average on price array                   |
//+------------------------------------------------------------------+
int LinearWeightedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& buffer[],int &weightsum)
{
int        i,limit;
double     sum;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
if(as_series_price)  ArraySetAsSeries(price,false);
if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
weightsum=0;
limit=period+begin;
//--- set empty value for first bars
for(i=0;i<limit;i++) buffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
{
int k=i-begin+1;
weightsum+=k;
firstValue+=k*price[i];
}
firstValue/=(double)weightsum;
buffer[limit-1]=firstValue;
}
else limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total;i++)
{
sum=0;
for(int j=0;j<period;j++) sum+=(period-j)*price[i-j];
buffer[i]=sum/weightsum;
}
//--- restore as_series flags
if(as_series_price)  ArraySetAsSeries(price,true);
if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
//|  Smoothed moving average on price array                          |
//+------------------------------------------------------------------+
int SmoothedMAOnBuffer(const int rates_total,const int prev_calculated,const int begin,
const int period,const double& price[],double& buffer[])
{
int i,limit;
//--- check for data
if(period<=1 || rates_total-begin<period) return(0);
//--- save as_series flags
bool as_series_price=ArrayGetAsSeries(price);
bool as_series_buffer=ArrayGetAsSeries(buffer);
if(as_series_price)  ArraySetAsSeries(price,false);
if(as_series_buffer) ArraySetAsSeries(buffer,false);
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
limit=period+begin;
//--- set empty value for first bars
for(i=0;i<limit-1;i++) buffer[i]=0.0;
//--- calculate first visible value
double firstValue=0;
for(i=begin;i<limit;i++)
firstValue+=price[i];
firstValue/=period;
buffer[limit-1]=firstValue;
}
else limit=prev_calculated-1;
//--- main loop
for(i=limit;i<rates_total;i++)
buffer[i]=(buffer[i-1]*(period-1)+price[i])/period;
//--- restore as_series flags
if(as_series_price)  ArraySetAsSeries(price,true);
if(as_series_buffer) ArraySetAsSeries(buffer,true);
//---
return(rates_total);
}
//+------------------------------------------------------------------+
```

```//+------------------------------------------------------------------+
//|                                              moving_averages.mq4 |
//|                        Copyright 2014, MetaQuotes Software Corp. |
//+------------------------------------------------------------------+
#property version   "1.00"
#property strict
#property indicator_chart_window
#property indicator_buffers 3
#property indicator_plots   3
//--- plot SMA
#property indicator_label1  "SMA"
#property indicator_type1   DRAW_LINE
#property indicator_color1  clrRed
#property indicator_style1  STYLE_SOLID
#property indicator_width1  1
//--- plot WMA
#property indicator_label2  "WMA"
#property indicator_type2   DRAW_LINE
#property indicator_color2  clrBlue
#property indicator_style2  STYLE_SOLID
#property indicator_width2  1
//--- plot EMA
#property indicator_label3  "EMA"
#property indicator_type3   DRAW_LINE
#property indicator_color3  clrGreen
#property indicator_style3  STYLE_SOLID
#property indicator_width3  1
//--- input parameters
input int      period=19;
//--- indicator buffers
double         SMABuffer[];
double         WMABuffer[];
double         EMABuffer[];
//+------------------------------------------------------------------+
//| Custom indicator initialization function                         |
//+------------------------------------------------------------------+
int OnInit()
{
IndicatorBuffers(3);
//--- indicator buffers mapping
SetIndexBuffer(0,SMABuffer);
SetIndexBuffer(1,WMABuffer);
SetIndexBuffer(2,EMABuffer);
string shortname = "EMA("+string(MODE_SMA)+")WMA("+string(MODE_LWMA)+")EMA("+string(MODE_EMA)+"["+string(period)+"]";
IndicatorShortName(shortname);
SetIndexLabel(0,"SMA");
SetIndexLabel(1,"WMA");
SetIndexLabel(2,"EMA");
SetIndexDrawBegin(0,period);
SetIndexDrawBegin(1,period);
SetIndexDrawBegin(2,period);
IndicatorDigits(Digits);

if(period<2)
return(INIT_FAILED);
//---
return(INIT_SUCCEEDED);
}
//+------------------------------------------------------------------+
//| Custom indicator iteration function                              |
//+------------------------------------------------------------------+
int OnCalculate(const int rates_total,
const int prev_calculated,
const datetime &time[],
const double &open[],
const double &high[],
const double &low[],
const double &close[],
const long &tick_volume[],
const long &volume[],
{
//---
if(rates_total < period -1 || period <2)
{
return 0;
}
ArraySetAsSeries(SMABuffer,false);
ArraySetAsSeries(WMABuffer,false);
ArraySetAsSeries(EMABuffer,false);
ArraySetAsSeries(close,false);
if(prev_calculated==0){
ArrayInitialize(SMABuffer,0);
ArrayInitialize(WMABuffer,0);
ArrayInitialize(EMABuffer,0);
}

CalculateSimpleMA(rates_total,prev_calculated,close);
CalculateLWMA(rates_total,prev_calculated,close);
CalculateEMA(rates_total,prev_calculated,close);

//--- return value of prev_calculated for next call
return(rates_total);
}
//+------------------------------------------------------------------+
void CalculateSimpleMA(int rates_total,int prev_calculated,const double &price[])
{
int i,limit;
//--- first calculation or number of bars was changed
if(prev_calculated==0)

{
limit=period;
//--- calculate first visible value
double firstValue=0;
for(i=0; i<limit; i++)
firstValue+=price[i];
firstValue/=period;
SMABuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit; i<rates_total && !IsStopped(); i++)
SMABuffer[i]=SMABuffer[i-1]+(price[i]-price[i-period])/period;
//---
}
//+------------------------------------------------------------------+
//|  exponential moving average                                      |
//+------------------------------------------------------------------+
void CalculateEMA(int rates_total,int prev_calculated,const double &price[])
{
int    i,limit;
double SmoothFactor=2.0/(1.0+period);
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
limit=period;
EMABuffer[0]=price[0];
for(i=1; i<limit; i++)
EMABuffer[i]=price[i]*SmoothFactor+EMABuffer[i-1]*(1.0-SmoothFactor);
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit; i<rates_total && !IsStopped(); i++)
EMABuffer[i]=price[i]*SmoothFactor+EMABuffer[i-1]*(1.0-SmoothFactor);
//---
}
//+------------------------------------------------------------------+
//|  linear weighted moving average                                  |
//+------------------------------------------------------------------+
void CalculateLWMA(int rates_total,int prev_calculated,const double &price[])
{
int        i,limit;
static int weightsum;
double     sum;
//--- first calculation or number of bars was changed
if(prev_calculated==0)
{
weightsum=0;
limit=period;
//--- calculate first visible value
double firstValue=0;
for(i=0;i<limit;i++)
{
int k=i+1;
weightsum+=k;
firstValue+=k*price[i];
}
firstValue/=(double)weightsum;
WMABuffer[limit-1]=firstValue;
}
else
limit=prev_calculated-1;
//--- main loop
for(i=limit; i<rates_total && !IsStopped(); i++)
{
sum=0;
for(int j=0;j<period;j++)
sum+=(period-j)*price[i-j];
WMABuffer[i]=sum/weightsum;
}
}```

Ok,今天介绍的MA指标就这样了，下次介绍MACD指标

CI中加入生成一维码的lib

2.解压后，将class文件夹放到application/libraries下面，可以改名为barcode，如果需要用他字体的话，font也放到你放字体的地方
3.application/libraries下面新建Barcode.php

```<?php
include 'barcode/BCGFontFile.php';
include 'barcode/BCGColor.php';
include 'barcode/BCGDrawing.php';

include 'barcode/BCGcode39.barcode.php';

class Barcode {
public \$colorFront;
public \$colorBlack;
public \$font;

function __construct(){
\$this->colorBlack = new BCGColor(255,255,255);
\$this->colorFront = new BCGColor(0,0,0);
//        \$this->font = new BCGFontFile('/assets/font/Arial.ttf', 18);//需要字体在这里指定
}

public function genBarcode(\$text) {
\$code = new BCGcode39();

\$code->setScale(2); // Resolution
\$code->setThickness(30); // Thickness
\$code->setForegroundColor(\$this->colorFront); // Color of bars
\$code->setBackgroundColor(\$this->colorBlack); // Color of spaces
//        \$code->setFont(\$this->font); // Font (or 0)
\$code->parse(\$text); // Text

\$drawing = new BCGDrawing('', \$this->colorBlack);
\$drawing->setBarcode(\$code);
\$drawing->draw();

\$drawing->finish((BCGDrawing::IMG_FORMAT_PNG));
}
}```

计算web访客的一个会话识别算法的php实现

```/**
* @param \$data array(key=>array((int)view_time,url,referer)) order by value asc
* @param \$threshold
* @param \$delta
* @return boolean
*/
function uvAlgorithm(\$data, \$threshold, \$delta) {
\$stack = array();
\$rangeDown = \$data[0]['view_time'];
\$vid = md5(\$rangeDown);
\$rangeUp = \$data[0]['view_time'] + \$threshold;
//    echo \$rangeDown . '~' . \$rangeUp . "\n";
//    print_r(\$data);
foreach (\$data as \$k=>\$v) {
if (\$k == 0) {
updateVisitId(\$v['id'], \$vid);
\$stack[] = \$v['url'];
continue;
}
if (\$v['view_time'] >= \$rangeDown && \$v['view_time'] < \$rangeUp) {
if (in_array(\$v['referer'], \$stack) || (\$data[\$k]['view_time'] - \$data[\$k - 1]['view_time'] < \$delta)) {
\$stack[] = \$v['url'];
updateVisitId(\$v['id'], \$vid);
}
else {
updateVisitId(\$v['id'], md5(\$v['view_time']));
}

}
else {
\$temp = array_splice(\$data, \$k);
//            print_r(\$temp);
//            print_r(\$data);
//            print_r(\$stack);
\$stack = array();
if (empty(\$temp)) {
return false;
}
else {
uvAlgorithm(\$temp, \$threshold, \$delta);
}
}
}
}```

Life is so hard, I’m too tired to insist on it

….

<父亲罹患PCa T3b 辗转3000公里求医记,整理中>

what’s rsync

rsync(remote synchronization)是*nix下一款同步软件，用于远程同步，备份文件，当然也可以本地做同步备份操作。

rsync 可以在中断之后恢复传输；它只传输源文件和目标文件之间不一致的部分；rsync 可以执行完整备份或增量备份。更棒的是，在所有风格的 UNIX 上都可以使用 rsync，包括 Mac OS X，所以很容易连接任何系统。

how to use rsync

shell模式(本地模式)

```[root@localhost tmp]# tree -L 2
.
├── rsync1
│   ├── 1.txt
│   ├── a.txt
│   ├── c.txt
│   └── v.txt
├── rsync2
│   └── 1.txt
```

```[root@localhost tmp]# rsync -avz rsync1/ rsync2
sending incremental file list
./
a.txt
c.txt
v.txt

sent 189 bytes  received 72 bytes  522.00 bytes/sec
total size is 0  speedup is 0.00
```

远程shell模式

```[root@localhost tmp]# rsync -avz rsync1/ root@192.168.22.81:/tmp
sending incremental file list
./
1.txt
a.txt
c.txt
v.txt

sent 225 bytes  received 91 bytes  9.16 bytes/sec
total size is 0  speedup is 0.00
```

列表模式

```[root@localhost tmp]# rsync rsync1/
drwxr-xr-x        4096 2014/02/20 13:42:21 .
-rw-r--r--           0 2014/02/18 16:41:47 1.txt
-rw-r--r--           0 2014/02/20 13:42:21 a.txt
-rw-r--r--           0 2014/02/20 13:42:21 c.txt
-rw-r--r--           0 2014/02/20 13:42:21 v.txt
```

服务器模式

```[root@localhost rsyncd]# pwd && ll
/etc/rsyncd
total 12
-rw-r--r-- 1 root root 808 Feb 19 16:21 rsyncd.conf
-rw-r--r-- 1 root root  36 Feb 19 15:10 rsyncd.motd
-rw------- 1 root root  12 Feb 19 15:10 rsyncd.secrets
```

`rsyncd.conf`是主要配置文件，

```pid file = /var/run/rsyncd.pid
port = 873
uid = root
gid = root
use chroot = yes

hosts allow=*
#hosts deny=*

max connections = 5
motd file = /etc/rsyncd/rsyncd.motd

#This will give you a separate log file
log file = /var/log/rsync.log

#This will log every file transferred - up to 85,000+ per user, per sync
#transfer logging = yes

log format = %t %a %m %f %b
syslog facility = local3
timeout = 300

[root_tmpTrans]
path = /tmp/rsnctrans
list=yes
ignore errors
auth users = root
secrets file = /etc/rsyncd/rsyncd.secrets
comment = balabala
exclude =   .git/ .svn/
```

`rsyncd.secrets`是执行同步、备份的账号,格式为`user:password`

```root:123456
```

`rsyncd.motd`是执行时的欢迎信息(message of the day)

```hi---------------------------------
```

```rsync --daemon --config=/etc/rsyncd.conf
```

```root@ubuntu:/tmp# rsync 192.168.22.81::
hi---------------------------------

root_tmpTrans   balabala
```

```root@ubuntu:/tmp# rsync 192.168.22.81::root_tmpTrans
hi---------------------------------

drwxr-xr-x        4096 2014/02/19 16:43:38 .
-rw-r--r--           0 2014/02/19 15:13:19 a.txt
-rw-r--r--           0 2014/02/19 16:43:38 c.txt
-rw-r--r--           0 2014/02/19 16:37:40 v.txt
```

坑1：

```\$a = 'test';
echo \$a['bdd'];```

`t`

坑2：

max_input_vars来做修改。

sed的模式空间和暂存空间

————sed是一个批处理（非交互式）编辑器。它可以变换来自文件或者标准输入的输入流。它常被用作管道中的过滤器。由于sed仅仅对其输入扫描一次，因此它比其他交互式编辑器（如ed）更高效。大多数linux发行版都提供了GNU sed，Mac OS X提供了BSD sed。『A Practical Guide to Linux Commands, Editors, and Shell Programming, chapter 13』

sed和awk一样，都是经典的linux神器，网上有大量相关教程，比如很不错的左耳朵耗子博客。今天想记录下之前并没有理解透的暂存空间和模式空间相关的操作(感觉自己智商一直在下降- -)。

g： 将hold space中的内容拷贝到pattern space中，原来pattern space里的内容清除
G： 将hold space中的内容append到pattern space\n后
h： 将pattern space中的内容拷贝到hold space中，原来的hold space里的内容被清除
H： 将pattern space中的内容append到hold space\n后
x： 交换pattern space和hold space的内容

```aladdin@ubuntu:~/tmp\$ cat sedtext
line one
line two
line three```

```aladdin@ubuntu:~/tmp\$ sed '2,\$G;h;\$!d' sedtext
line three
line two
line one```

2,\$G:从第二行到最后一行执行G命令

h:执行h命令

\$!d:删除除了最后一行的所有行